自己做代練網(wǎng)站百度關(guān)鍵詞廣告怎么收費(fèi)
本項(xiàng)目就是基于TCP網(wǎng)絡(luò)通信搭建的。
TCP:
客戶端:socket(),connect().
服務(wù)端:socket(),bind(),listen(),accept().
下面代碼就是對(duì)原生API網(wǎng)絡(luò)套接字的封裝。需要熟悉原生API網(wǎng)絡(luò)套接字接口。
下面這段代碼,沒(méi)什么好講的,就不再講了。下面代碼會(huì)涉及文件描述符的相關(guān)設(shè)置,我會(huì)專出一篇文章,進(jìn)行講解。
#define MAX_LISTEN 1024
class Socket {private:int _sockfd;public:Socket():_sockfd(-1) {}Socket(int fd): _sockfd(fd) {}~Socket() { Close(); }int Fd() { return _sockfd; }//創(chuàng)建套接字bool Create() {// int socket(int domain, int type, int protocol)_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (_sockfd < 0) {ERR_LOG("CREATE SOCKET FAILED!!");return false;}return true;}//綁定地址信息bool Bind(const std::string &ip, uint16_t port) {struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip.c_str());socklen_t len = sizeof(struct sockaddr_in);// int bind(int sockfd, struct sockaddr*addr, socklen_t len);int ret = bind(_sockfd, (struct sockaddr*)&addr, len);if (ret < 0) {ERR_LOG("BIND ADDRESS FAILED!");return false;}return true;}//開(kāi)始監(jiān)聽(tīng)bool Listen(int backlog = MAX_LISTEN) {// int listen(int backlog)int ret = listen(_sockfd, backlog);if (ret < 0) {ERR_LOG("SOCKET LISTEN FAILED!");return false;}return true;}//向服務(wù)器發(fā)起連接bool Connect(const std::string &ip, uint16_t port) {struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip.c_str());socklen_t len = sizeof(struct sockaddr_in);// int connect(int sockfd, struct sockaddr*addr, socklen_t len);int ret = connect(_sockfd, (struct sockaddr*)&addr, len);if (ret < 0) {ERR_LOG("CONNECT SERVER FAILED!");return false;}return true;}//獲取新連接int Accept() {// int accept(int sockfd, struct sockaddr *addr, socklen_t *len);int newfd = accept(_sockfd, NULL, NULL);//不需要獲取客戶端信息 就可以將他們置NULLif (newfd < 0) {ERR_LOG("SOCKET ACCEPT FAILED!");return -1;}return newfd;}//接收數(shù)據(jù)ssize_t Recv(void *buf, size_t len, int flag = 0) {// ssize_t recv(int sockfd, void *buf, size_t len, int flag);ssize_t ret = recv(_sockfd, buf, len, flag);if (ret <= 0) {//EAGAIN 當(dāng)前socket的接收緩沖區(qū)中沒(méi)有數(shù)據(jù)了,在非阻塞的情況下才會(huì)有這個(gè)錯(cuò)誤//EINTR 表示當(dāng)前socket的阻塞等待,被信號(hào)打斷了,if (errno == EAGAIN || errno == EINTR) {return 0;//表示這次接收沒(méi)有接收到數(shù)據(jù)}ERR_LOG("SOCKET RECV FAILED!!");return -1;}return ret; //實(shí)際接收的數(shù)據(jù)長(zhǎng)度}ssize_t NonBlockRecv(void *buf, size_t len) {return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示當(dāng)前接收為非阻塞。}//發(fā)送數(shù)據(jù)ssize_t Send(const void *buf, size_t len, int flag = 0) {// ssize_t send(int sockfd, void *data, size_t len, int flag);ssize_t ret = send(_sockfd, buf, len, flag);if (ret < 0) {if (errno == EAGAIN || errno == EINTR) {return 0;}ERR_LOG("SOCKET SEND FAILED!!");return -1;}return ret;//實(shí)際發(fā)送的數(shù)據(jù)長(zhǎng)度}ssize_t NonBlockSend(void *buf, size_t len) {if (len == 0) return 0;return Send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示當(dāng)前發(fā)送為非阻塞。}//關(guān)閉套接字void Close() {if (_sockfd != -1) {close(_sockfd);_sockfd = -1;}}//創(chuàng)建一個(gè)服務(wù)端連接bool CreateServer(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false) {//1. 創(chuàng)建套接字,2. 綁定地址,3. 開(kāi)始監(jiān)聽(tīng),4. 設(shè)置非阻塞, 5. 啟動(dòng)地址重用if (Create() == false) return false;if (block_flag) NonBlock();if (Bind(ip, port) == false) return false;if (Listen() == false) return false;ReuseAddress();return true;}//創(chuàng)建一個(gè)客戶端連接bool CreateClient(uint16_t port, const std::string &ip) {//1. 創(chuàng)建套接字,2.指向連接服務(wù)器if (Create() == false) return false;if (Connect(ip, port) == false) return false;return true;}//設(shè)置套接字選項(xiàng)---開(kāi)啟地址端口重用void ReuseAddress() {// int setsockopt(int fd, int leve, int optname, void *val, int vallen)int val = 1;setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int));val = 1;setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&val, sizeof(int));}//設(shè)置套接字阻塞屬性-- 設(shè)置為非阻塞void NonBlock() {//int fcntl(int fd, int cmd, ... /* arg */ );int flag = fcntl(_sockfd, F_GETFL, 0);fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);}
};