国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

歐美網(wǎng)站欣賞搜索引擎營(yíng)銷實(shí)訓(xùn)報(bào)告

歐美網(wǎng)站欣賞,搜索引擎營(yíng)銷實(shí)訓(xùn)報(bào)告,企業(yè)名錄搜索,什么做電子書(shū)下載網(wǎng)站🔥 個(gè)人主頁(yè):大耳朵土土垚 🔥 所屬專欄:Linux系統(tǒng)編程 這里將會(huì)不定期更新有關(guān)Linux的內(nèi)容,歡迎大家點(diǎn)贊,收藏,評(píng)論🥳🥳🎉🎉🎉 文章目…
🔥 個(gè)人主頁(yè):大耳朵土土垚
🔥 所屬專欄:Linux系統(tǒng)編程

這里將會(huì)不定期更新有關(guān)Linux的內(nèi)容,歡迎大家點(diǎn)贊,收藏,評(píng)論🥳🥳🎉🎉🎉

文章目錄

  • 1.Echo server
  • 2. Dict server
  • 3. ChatServer

1.Echo server

簡(jiǎn)單的回顯服務(wù)器和客戶端代碼。

  • 服務(wù)器代碼:
#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <cerrno>
#include <strings.h>#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include "Log.hpp"
#include "InetAddr.hpp"
#include "Common.hpp"using namespace LogModule;
using namespace InetAddrModule;const static int gsockfd = -1;
const static uint16_t gdefaultport = 8080;class UdpServer
{
public:UdpServer(uint16_t port = gdefaultport): _sockfd(gsockfd),_addr(port),_isrunning(false){}void InitServer(){// 1. 創(chuàng)建socket_sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){LOG(LogLevel::FATAL) << "socket: " << strerror(errno);Die(SOCKET_ERR);}LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;// 2. bind : 設(shè)置進(jìn)入內(nèi)核中int n = ::bind(_sockfd, _addr.NetAddr(), _addr.NetAddrLen());if (n < 0){LOG(LogLevel::FATAL) << "bind: " << strerror(errno);Die(BIND_ERR);}LOG(LogLevel::INFO) << "bind success";}bool Start(){_isrunning = true;while (true){char inbuffer[1024]; // stringstruct sockaddr_in peer;socklen_t len = sizeof(peer); // 必須設(shè)定ssize_t n = ::recvfrom(_sockfd, inbuffer, sizeof(inbuffer)-1, 0, CONV(&peer),&len);if(n > 0){inbuffer[n] = 0;InetAddr client(peer);//獲取cilent相關(guān)信息std::string cilentmessage = client.Ip()+":"+std::to_string(client.Port())+"# "+ inbuffer;LOG(LogLevel::DEBUG)<<cilentmessage;//將獲取到的信息寫(xiě)回clientstd::string echo_string = "echo# ";echo_string += inbuffer;::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,client.NetAddr(),client.NetAddrLen());}}_isrunning = false;}~UdpServer(){if (_sockfd > gsockfd)::close(_sockfd);}private:InetAddr _addr; // 服務(wù)器地址包括ip和portint _sockfd;bool _isrunning; // 服務(wù)器運(yùn)行狀態(tài)
};#endif

要使用網(wǎng)絡(luò)服務(wù)器需要使用socket創(chuàng)建套接字,然后將IP和端口號(hào)bind進(jìn)入內(nèi)核,最后就可以調(diào)用recv/sendto接口進(jìn)行網(wǎng)絡(luò)發(fā)送和接收信息了

服務(wù)器使用代碼:


#include "UdpServer.hpp"// ./server_udp localport
int main(int argc, char *argv[])
{ENABLE_CONSOLE_LOG_STRATEGY();std::unique_ptr<UdpServer> svr_uptr;if (argc == 2){uint16_t port = std::stoi(argv[1]);svr_uptr = std::make_unique<UdpServer>(port);}elsesvr_uptr = std::make_unique<UdpServer>();svr_uptr->InitServer();svr_uptr->Start();return 0;
}

服務(wù)器需要輸入端口號(hào),不輸入也行,服務(wù)器默認(rèn)端口號(hào)為8080

  • 客戶端代碼:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"using namespace LogModule;
using namespace InetAddrModule;int sockfd = -1;//./udp_client server_ip server_port
int main(int argc, char *argv[])
{if(argc!=3){LOG(LogLevel::ERROR)<<"Usage:" << argv[0] << " serverip serverport" ;Die(ARGV_ERR);}//1.創(chuàng)建sockfdsockfd = ::socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){LOG(LogLevel::WARNING)<<"client sockfd fail...";Die(SOCKET_ERR);} LOG(LogLevel::INFO)<<"client sockfd success...";//2.填充服務(wù)器信息std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);InetAddr ServerAddr(serverip,serverport);//3.發(fā)送請(qǐng)求給服務(wù)器while(true){//3.1獲取信息std::cout << "Please Enter# ";std::string message;std::getline(std::cin, message);//3.2發(fā)送信息給服務(wù)器ssize_t n = ::sendto(sockfd,message.c_str(),sizeof(message),0,ServerAddr.NetAddr(),ServerAddr.NetAddrLen());if(n < 0){LOG(LogLevel::ERROR)<<"client sendto fail...";continue;}//3.3從服務(wù)器接收信息char buffer[1024];struct sockaddr_in tmp;socklen_t len = sizeof(tmp);ssize_t m = ::recvfrom(sockfd,buffer,sizeof(buffer)-1,0,CONV(&tmp),&len);if(m > 0){buffer[m] = 0;std::cout<<buffer<<std::endl;}else{LOG(LogLevel::ERROR)<<"client recvfrom fail...";}}return 0;
}

同樣,客戶端要進(jìn)行網(wǎng)絡(luò)通信也需要?jiǎng)?chuàng)建套接字,但是不需要bind信息進(jìn)入內(nèi)核,因?yàn)樵诮邮盏骄W(wǎng)絡(luò)信息時(shí)會(huì)自動(dòng)進(jìn)行bind

客戶端需要輸入服務(wù)器IP地址和端口號(hào)port

  • 網(wǎng)絡(luò)地址類:

因?yàn)樵谶M(jìn)行網(wǎng)絡(luò)通信時(shí)不可避免的需要頻繁使用到相關(guān)信息,所以我們可以考慮將它們封裝成為一個(gè)類,設(shè)置一些常用的方法

#pragma once#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Common.hpp"namespace InetAddrModule
{class InetAddr{private:void PortNet2Host() // port網(wǎng)絡(luò)轉(zhuǎn)主機(jī){_port = ::ntohs(_net_addr.sin_port);}void IpNet2Host() // IP網(wǎng)絡(luò)轉(zhuǎn)主機(jī){char ipbuffer[64];const char *ip = ::inet_ntop(AF_INET, &_net_addr.sin_addr, ipbuffer, sizeof(ipbuffer));_ip = ip;}public:InetAddr(){}InetAddr(const struct sockaddr_in &addr) : _net_addr(addr) // 獲取傳來(lái)的sockaddr的ip和port{PortNet2Host();IpNet2Host();}InetAddr(uint16_t port) : _port(port), _ip(""){_net_addr.sin_family = AF_INET;_net_addr.sin_port = htons(_port);//主機(jī)轉(zhuǎn)網(wǎng)絡(luò)_net_addr.sin_addr.s_addr = INADDR_ANY;//表示可以介紹任何ip地址}InetAddr(const std::string& ip,uint16_t port) : _port(port), _ip(ip){_net_addr.sin_family = AF_INET;_net_addr.sin_port = htons(_port);//主機(jī)轉(zhuǎn)網(wǎng)絡(luò)_net_addr.sin_addr.s_addr = ::inet_addr(ip.c_str());}struct sockaddr *NetAddr() { return CONV(&_net_addr); }socklen_t NetAddrLen() { return sizeof(_net_addr); }std::string Ip() { return _ip; }uint16_t Port() { return _port; }~InetAddr(){}private:struct sockaddr_in _net_addr;std::string _ip;uint16_t _port;};
}

因?yàn)楦鞣N機(jī)器之間不兼容等例如大端/小端模式,所以在實(shí)際進(jìn)行網(wǎng)絡(luò)通信時(shí)我們需要將發(fā)送的ip地址和端口號(hào)從主機(jī)模式轉(zhuǎn)換為網(wǎng)絡(luò)模式。

在網(wǎng)絡(luò)編程中,當(dāng)一個(gè)進(jìn)程需要綁定一個(gè)網(wǎng)絡(luò)端口以進(jìn)行通信時(shí),可以使用INADDR_ANY 作為 IP 地址參數(shù)。這樣做意味著該端口可以接受來(lái)自任何 IP 地址的連接請(qǐng)求,無(wú)論是本地主機(jī)還是遠(yuǎn)程主機(jī)。例如,如果服務(wù)器有多個(gè)網(wǎng)卡(每個(gè)網(wǎng)卡上有不同的 IP 地址),使用 INADDR_ANY 可以省去確定數(shù)據(jù)是從服務(wù)器上具體哪個(gè)網(wǎng)卡/IP 地址上面獲取的。

結(jié)果如下:

在這里插入圖片描述

2. Dict server

??上述echo server僅僅是將收到的消息回顯給客戶端,其實(shí)我們還可以在服務(wù)器中加一點(diǎn)業(yè)務(wù)處理,比如翻譯功能。

??所以我們可以創(chuàng)建一個(gè)Dictionary類,將翻譯詞典封裝起來(lái):

Dict.txt:

apple: 蘋(píng)果
banana: 香蕉
cat: 貓
dog: 狗
book: 書(shū)
pen: 筆
happy: 快樂(lè)的
sad: 悲傷的
run: 跑
jump: 跳
teacher: 老師
student: 學(xué)生
car: 汽車
bus: 公交車
love: 愛(ài)
hate: 恨
hello: 你好
goodbye: 再見(jiàn)
summer: 夏天
winter: 冬天

Dict.hpp:

#pragma once#include <iostream>
#include <fstream>
#include <unordered_map>
#include "Log.hpp"namespace DictionaryModule
{const std::string sep = ": "; // 分割符using namespace LogModule;class Dict{private://將詞典內(nèi)容從Dict.txt中加載進(jìn)來(lái)void DownloadDict(){std::ifstream in(_dictpath);if (!in.is_open()){LOG(LogLevel::WARNING) << "DownloadDict fail...";return;}std::string line;while (getline(in, line)){if (line.empty())continue;// 加入詞典size_t pos = line.find(sep);_dict.insert({line.substr(0, pos), line.substr(pos + sep.size())});}}public:Dict(const std::string &dictpath = "./Dict.txt") : _dictpath(dictpath){DownloadDict(); // 加載詞典}std::string Translate(const std::string &key){auto iter = _dict.find(key);if (iter == _dict.end())return std::string("Unknown");elsereturn iter->second;}~Dict(){}private:std::string _dictpath;std::unordered_map<std::string, std::string> _dict;};
}

??有了翻譯的功能后,我們就可以將其嵌入服務(wù)器內(nèi)部使用,所以我們?cè)?code>UdpServer類成員中添加一個(gè)回調(diào)方法,并在Start函數(shù)中使用:

#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <cerrno>
#include <strings.h>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include "Log.hpp"
#include "InetAddr.hpp"
#include "Common.hpp"using namespace LogModule;
using namespace InetAddrModule;using func_t = std::function<std::string(const std::string&)>;
const static int gsockfd = -1;
const static uint16_t gdefaultport = 8080;class UdpServer
{
public:UdpServer(func_t func,uint16_t port = gdefaultport): _sockfd(gsockfd),_addr(port),_isrunning(false),_func(func){}void InitServer(){// 1. 創(chuàng)建socket_sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0){LOG(LogLevel::FATAL) << "socket: " << strerror(errno);Die(SOCKET_ERR);}LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;// 2. bind : 設(shè)置進(jìn)入內(nèi)核中int n = ::bind(_sockfd, _addr.NetAddr(), _addr.NetAddrLen());if (n < 0){LOG(LogLevel::FATAL) << "bind: " << strerror(errno);Die(BIND_ERR);}LOG(LogLevel::INFO) << "bind success";}bool Start(){_isrunning = true;while (true){char inbuffer[1024]; // stringstruct sockaddr_in peer;socklen_t len = sizeof(peer); // 必須設(shè)定ssize_t n = ::recvfrom(_sockfd, inbuffer, sizeof(inbuffer)-1, 0, CONV(&peer),&len);if(n > 0){inbuffer[n] = 0;InetAddr client(peer);//獲取cilent相關(guān)信息std::string cilentmessage = client.Ip()+":"+std::to_string(client.Port())+"# "+ inbuffer;LOG(LogLevel::DEBUG)<<cilentmessage;//調(diào)用回調(diào)方法處理翻譯業(yè)務(wù)std::string value = _func(inbuffer);//將獲取到的信息寫(xiě)回clientstd::string echo_string = "Translate# ";echo_string += value;::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,client.NetAddr(),client.NetAddrLen()); }}_isrunning = false;}~UdpServer(){if (_sockfd > gsockfd)::close(_sockfd);}private:InetAddr _addr; // 服務(wù)器地址包括ip和portint _sockfd;bool _isrunning; // 服務(wù)器運(yùn)行狀態(tài)func_t _func; //回調(diào)業(yè)務(wù)方法
};#endif

??最后在定義服務(wù)器時(shí)使用lambda表達(dá)式將Dict類中的Translate方法綁定給UdpServer


#include "UdpServer.hpp"
#include "Dict.hpp"using namespace DictionaryModule;// ./server_udp localport
int main(int argc, char *argv[])
{ENABLE_CONSOLE_LOG_STRATEGY();Dict dictionary;std::unique_ptr<UdpServer> svr_uptr;if (argc == 2){uint16_t port = std::stoi(argv[1]);svr_uptr = std::make_unique<UdpServer>([&dictionary](const std::string& key){return dictionary.Translate(key);},port);}elsesvr_uptr = std::make_unique<UdpServer>([&dictionary](const std::string& key){return dictionary.Translate(key);});svr_uptr->InitServer();svr_uptr->Start();return 0;
}

客戶端函數(shù)不需要改變可以直接使用,結(jié)果如下:

在這里插入圖片描述

3. ChatServer

??對(duì)于聊天室的實(shí)現(xiàn),我們需要對(duì)聊天對(duì)象進(jìn)行管理,所以需要新建一個(gè)類usermanager以及描述聊天對(duì)象的類user:

#pragma once#include <iostream>
#include <list>
#include <memory>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"
namespace UserModule
{using namespace InetAddrModule;using namespace LogModule;using namespace MutexModule;class UserInterface{public:virtual ~UserInterface() = default;virtual void SendTo(int sockfd, const std::string &message) = 0; // 純虛函數(shù)virtual bool operator==(const InetAddr &u) const = 0;virtual std::string Id() = 0;};//描述對(duì)象class User : public UserInterface{public:User(const InetAddr &id) : _id(id){}void SendTo(int sockfd, const std::string &message) override{// ssize_t n = ::sendto(sockfd, &message, message.size(), 0, _id.NetAddr(), _id.NetAddrLen());錯(cuò)誤錯(cuò)誤!!!!不能取地址messagessize_t n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info: " << message;if (n < 0){LOG(LogLevel::WARNING) << "Snedto fail...";return;}}bool operator==(const InetAddr &u) const override{return _id == u;}std::string Id(){return _id.Addr();}~User(){}private:InetAddr _id;};//管理對(duì)象class UserManage{public:UserManage(){}void AddUser(InetAddr &id){LockGuard lock(_mutex);//因?yàn)橐L問(wèn)公共資源所以要加鎖保護(hù)// 1.先遍歷整個(gè)鏈表查找是否已經(jīng)添加過(guò)了for (auto &user : _online_user){if (*user == id) // User已經(jīng)重載=={LOG(LogLevel::INFO) << id.Addr() << "用戶已經(jīng)存在...";return;}}// 2.如果是新用戶就添加_online_user.push_back(std::make_shared<User>(id));LOG(LogLevel::INFO) << "添加用戶: " << id.Addr() << "成功...";}void DelUser(InetAddr &id){LockGuard lock(_mutex);// 1.先遍歷整個(gè)鏈表查找是否有該用戶auto pos = std::remove_if(_online_user.begin(), _online_user.end(), [&id](std::shared_ptr<UserInterface> &user){ return *user == id; });// 2.如果有就刪除_online_user.erase(pos, _online_user.end());}// 路由轉(zhuǎn)發(fā)void Router(int sockfd, const std::string &message){LockGuard lock(_mutex);for (auto &user : _online_user){user->SendTo(sockfd, message);}}void PrintUser(){LockGuard lock(_mutex);for (auto user : _online_user){LOG(LogLevel::DEBUG) << "在線用戶-> " << user->Id();}}~UserManage(){}private:std::list<std::shared_ptr<UserInterface>> _online_user;Mutex _mutex;};
};

對(duì)于描述對(duì)象參數(shù)我們可以使用之前實(shí)現(xiàn)的InetAddr類,對(duì)于對(duì)象的管理方法主要有添加對(duì)象、刪除對(duì)象以及路由轉(zhuǎn)發(fā)(群發(fā))這三個(gè)部分;因?yàn)楹罄m(xù)有多個(gè)線程而它們內(nèi)部實(shí)現(xiàn)需要訪問(wèn)公共資源,所以需要加鎖保護(hù)。

??在服務(wù)器代碼中其他都與前面類似,我們只需要將服務(wù)器的Start方法修改一下即可:

bool Start(){_isrunning = true;while (true){char inbuffer[1024]; // stringstruct sockaddr_in peer;socklen_t len = sizeof(peer); // 必須設(shè)定ssize_t n = ::recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, CONV(&peer), &len);if (n > 0){inbuffer[n] = 0;InetAddr client(peer); // 1.獲取cilent相關(guān)信息std::string message = client.Addr() + "# " + inbuffer;LOG(LogLevel::DEBUG) << message;// 2.判斷是否為quit信息if (std::strcmp(inbuffer, "quit") == 0){_deluser(client);message = client.Addr() + "# " + "我走了,你們聊!";}else{// 3.添加新用戶_adduser(client);}// 3. 構(gòu)建轉(zhuǎn)發(fā)任務(wù),推送給線程池,讓線程池進(jìn)行轉(zhuǎn)發(fā)task_t task = std::bind(UdpServer::_router, _sockfd, message);ThreadPool<task_t>::GetInstance()->Enqueue(task);}}_isrunning = false;}

服務(wù)器不再是簡(jiǎn)單的接收信息,還需要對(duì)接收的消息進(jìn)行處理;因?yàn)檗D(zhuǎn)發(fā)任務(wù)消耗的時(shí)間可能較長(zhǎng),我們可以利用之前實(shí)現(xiàn)的線程池來(lái)處理多個(gè)轉(zhuǎn)發(fā)任務(wù),主線程則繼續(xù)收消息然后往線程池里添加轉(zhuǎn)發(fā)任務(wù)。

??除了Start方法,服務(wù)器類也需要添加幾個(gè)回調(diào)方法(在Start方法中使用):

using add_t = std::function<void(InetAddr &id)>;
using del_t = std::function<void(InetAddr &id)>;
using router_t = std::function<void(int sockfd, const std::string &message)>;
using task_t = std::function<void()>;
class UdpServer
{
public:UdpServer(add_t adduser, del_t deluser, router_t router, uint16_t port = gdefaultport): _sockfd(gsockfd),_addr(port),_isrunning(false),_adduser(adduser),_deluser(deluser),_router(router){}private:InetAddr _addr; // 服務(wù)器地址包括ip和portint _sockfd;bool _isrunning; // 服務(wù)器運(yùn)行狀態(tài)add_t _adduser;del_t _deluser;router_t _router;
};#endif

??在main函數(shù)中使用服務(wù)器對(duì)象時(shí)就需要綁定上述回調(diào)方法:


#include "UdpServer.hpp"
#include "User.hpp"
using namespace UserModule;// ./server_udp localport
int main(int argc, char *argv[])
{ENABLE_CONSOLE_LOG_STRATEGY();std::shared_ptr<UserManage> um = std::make_shared<UserManage>();std::unique_ptr<UdpServer> svr_uptr;if (argc == 2){uint16_t port = std::stoi(argv[1]);svr_uptr = std::make_unique<UdpServer>([&um](InetAddr &id){ return um->AddUser(id); },[&um](InetAddr &id){ return um->DelUser(id); },[&um](int sockfd, const std::string &message){ return um->Router(sockfd, message); },port);}elsesvr_uptr = std::make_unique<UdpServer>([&um](InetAddr &id){ return um->AddUser(id); },[&um](InetAddr &id){ return um->DelUser(id); },[&um](int sockfd, const std::string &message){ return um->Router(sockfd, message); });svr_uptr->InitServer();svr_uptr->Start();return 0;
}

??對(duì)于客戶端代碼,我們也需要?jiǎng)?chuàng)建兩個(gè)線程,主線程用來(lái)向服務(wù)器發(fā)送消息,另一個(gè)線程則用來(lái)接收群發(fā)的消息:

 #include "Common.hpp"
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>int sockfd = -1;
struct sockaddr_in server;void ClientQuit(int signo)
{(void)signo;const std::string quit = "QUIT";int n = ::sendto(sockfd, quit.c_str(), quit.size(), 0, CONV(&server), sizeof(server));exit(0);
}void *Recver(void *args)
{while (true){(void)args;struct sockaddr_in temp;socklen_t len = sizeof(temp);char buffer[1024];int n = ::recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, CONV(&temp), &len);if (n > 0){buffer[n] = 0;std::cout << buffer << std::endl; // 代碼沒(méi)問(wèn)題,重定向也沒(méi)問(wèn)題,管道讀寫(xiě)同時(shí)打開(kāi),才會(huì)繼續(xù)向后運(yùn)行// fprintf(stderr, "%s\n", buffer);// fflush(stderr);}}
}// CS
// ./client_udp serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){std::cerr << "Usage: " << argv[0] << " serverip serverport" << std::endl;Die(USAGE_ERR);}signal(2, ClientQuit);std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);// 1. 創(chuàng)建socketsockfd = ::socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;Die(SOCKET_ERR);}std::cout<<"sockfd: "<<sockfd<<std::endl;// 1.1 填充server信息memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = ::htons(serverport);server.sin_addr.s_addr = ::inet_addr(serverip.c_str());pthread_t tid;pthread_create(&tid, nullptr, Recver, nullptr);// 1.2 啟動(dòng)的時(shí)候,給服務(wù)器推送消息即可const std::string online = " ... 來(lái)了哈!";int n = ::sendto(sockfd, online.c_str(), online.size(), 0, CONV(&server), sizeof(server));// 2. clientdonewhile (true){std::cout << "Please Enter# ";std::string message;std::getline(std::cin, message);// client 不需要bind嗎?socket <-> socket// client必須也要有自己的ip和端口!但是客戶端,不需要自己顯示的調(diào)用bind!!// 而是,客戶端首次sendto消息的時(shí)候,由OS自動(dòng)進(jìn)行bind// 1. 如何理解client自動(dòng)隨機(jī)bind端口號(hào)? 一個(gè)端口號(hào),只能被一個(gè)進(jìn)程bind// 2. 如何理解server要顯示的bind?服務(wù)器的端口號(hào),必須穩(wěn)定!!必須是眾所周知且不能改變輕易改變的!int n = ::sendto(sockfd, message.c_str(), message.size(), 0, CONV(&server), sizeof(server));(void)n;}return 0;
}

在運(yùn)行客戶端代碼之前,我們可以創(chuàng)建一個(gè)管道將其重定向到cerro,然后運(yùn)行客戶端,這樣服務(wù)器群發(fā)收到的消息就會(huì)寫(xiě)入到管道中

http://aloenet.com.cn/news/30049.html

相關(guān)文章:

  • 大型自助建站平臺(tái)seo的方法
  • 網(wǎng)站建設(shè)體會(huì)電腦系統(tǒng)優(yōu)化軟件十大排名
  • 移動(dòng)網(wǎng)站如何做權(quán)重鎮(zhèn)江網(wǎng)站制作公司
  • 青島建設(shè)委員會(huì)網(wǎng)站網(wǎng)站關(guān)鍵詞優(yōu)化培訓(xùn)
  • wordpress幻燈片怎么建運(yùn)營(yíng)seo是什么意思
  • 不正規(guī)網(wǎng)站制作seo博客模板
  • 網(wǎng)頁(yè)設(shè)計(jì)網(wǎng)站鏈接怎么做公司網(wǎng)站推廣
  • 浦東網(wǎng)站建設(shè)公司網(wǎng)絡(luò)營(yíng)銷網(wǎng)站
  • 有什么免費(fèi)ppt模板網(wǎng)站好用的搜索引擎有哪些
  • dw怎樣去除網(wǎng)站做的頁(yè)面模板網(wǎng)站運(yùn)營(yíng)及推廣方案
  • 淘寶網(wǎng)站建設(shè)基本流程圖萬(wàn)網(wǎng)域名查詢接口
  • 手機(jī)網(wǎng)站制作與建設(shè)百度收錄網(wǎng)址提交
  • 今日軍事新聞聯(lián)播在線播放長(zhǎng)沙百度快照優(yōu)化排名
  • 優(yōu)質(zhì)網(wǎng)站建設(shè)報(bào)價(jià)長(zhǎng)沙seo網(wǎng)站優(yōu)化
  • 國(guó)外扁平化網(wǎng)站企業(yè)培訓(xùn)計(jì)劃方案
  • 建設(shè)類似衣聯(lián)網(wǎng)的網(wǎng)站整合營(yíng)銷名詞解釋
  • php做的網(wǎng)站怎么上傳網(wǎng)站推廣優(yōu)化
  • h5網(wǎng)站制作費(fèi)用關(guān)鍵字c語(yǔ)言
  • 模擬網(wǎng)站建設(shè)平臺(tái)推廣是做什么的
  • 可以自己做效果圖的網(wǎng)站小程序自助搭建平臺(tái)
  • 學(xué)生做網(wǎng)站期末作業(yè)新產(chǎn)品推廣方案怎么寫(xiě)
  • 做空氣開(kāi)關(guān)那個(gè)網(wǎng)站推廣比較好百度廣告聯(lián)盟app
  • 天津企業(yè)網(wǎng)站模板建站哪家好搜索自媒體平臺(tái)
  • 網(wǎng)站建設(shè)后的效果評(píng)估sem是什么意思啊
  • wordpress插件 地圖北京做網(wǎng)絡(luò)優(yōu)化的公司
  • 做網(wǎng)站推廣多少錢百度銷售系統(tǒng)
  • 柳州市黨風(fēng)廉政建設(shè)網(wǎng)站專注網(wǎng)站建設(shè)服務(wù)機(jī)構(gòu)
  • 青海報(bào)社網(wǎng)站建設(shè)公司百度在線問(wèn)答
  • 做的網(wǎng)站怎么放視頻如何做網(wǎng)站的教程
  • 網(wǎng)站建設(shè)一點(diǎn)通口碑營(yíng)銷是什么