c++實現封裝socket

來源:互聯網
上載者:User

編程執行個體:

CSocket.h

#include <iostream>#include<sys/socket.h>#include<sys/un.h>#include<netinet/in.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>#include <arpa/inet.h>#include <fcntl.h>#include <netdb.h>#include <stdio.h>#include <netinet/tcp.h>class CServSocket{public:    CServSocket();    virtual ~CServSocket();std::string  getLocalAddr();std::string getCliAddr();int getAcceptSock();bool Accept();    bool Listen(int port);bool Send(char* sendbuf, int len);bool Recv(char* recvbuf, int len, int timeout);private:bool Close();bool setSoLinger(bool dolinger, int seconds);bool setIntOptions(int option, int value);bool setTimeout(int option, int milliseconds);bool setNonBlock(bool isnonsocket);bool setNoDelay(bool nodelay);private:    char ip[20];int port;int sockfd;int connsockfd;struct sockaddr_in servAddr, cliAddr;};CServSocket::CServSocket():port(0),sockfd(-1),connsockfd(-1){memset(ip, 0, 20);}CServSocket::~CServSocket(){if(!Close()){std::cout << "close err\n";}}bool CServSocket::Close(){if(sockfd)close(sockfd);elsereturn false;if(connsockfd)    close(connsockfd);elsereturn false;sockfd = connsockfd = port = -1;return true;}bool CServSocket::Listen(int port){if(port < 0){std::cout <<"the port err\n";return false;}sockfd = ::socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){std::cout << "create socket err\n";return false;}getLocalAddr();servAddr.sin_family = AF_INET;if(ip)    servAddr.sin_addr.s_addr = inet_addr(ip);elseservAddr.sin_addr.s_addr = htonl(INADDR_ANY);servAddr.sin_port = htons(port);setSoLinger(false, 0);setIntOptions(SO_REUSEADDR,1);setIntOptions(SO_KEEPALIVE, 1);setIntOptions(SO_SNDBUF, 640000);setIntOptions(SO_RCVBUF, 640000);setNoDelay(true);if(::bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0){std::cout << "bind err\n";return false;}if(::listen(sockfd, 0) < 0){std::cout << "listen err\n";return false;}return true;}bool CServSocket::Accept(){socklen_t len = sizeof(cliAddr);if((connsockfd = ::accept(sockfd, (struct sockaddr*)&cliAddr, &len)) <0){return false;}return true;}std::string  CServSocket::getLocalAddr(){char ipaddr[20]={'\0'};const char* shellstr = "ifconfig | sed -n '2p' | awk -F'[ :]+' '{printf $4}'";      FILE *fp = popen(shellstr, "r");fread(ipaddr, sizeof(char), sizeof(ipaddr), fp);if(ipaddr){strcpy(ip, ipaddr);}pclose(fp);return std::string(ip);}std::string CServSocket::getCliAddr(){char cliip[16];socklen_t size = sizeof(cliAddr);if(getpeername(sockfd, (sockaddr*)&cliAddr, &size)){strcpy(cliip, "0.0.0.0");}else{        sprintf(cliip, "%d.%d.%d.%d", ((unsigned char*)&cliAddr.sin_addr)[0],((unsigned char*)&cliAddr.sin_addr)[1],((unsigned char*)&cliAddr.sin_addr)[2],((unsigned char*)&cliAddr.sin_addr)[3]);}return cliip;}int CServSocket::getAcceptSock(){return connsockfd;}bool CServSocket::setIntOptions(int option, int value){bool res = false;if(sockfd){res = (setsockopt(sockfd, SOL_SOCKET, option, (const void*)&value, sizeof(value)) == 0);}return res;}bool CServSocket::setSoLinger(bool dolinger, int seconds){bool res = false;if(sockfd){struct linger ling;ling.l_onoff = dolinger?1:0;ling.l_linger = seconds;res = (setsockopt(sockfd,SOL_SOCKET, SO_LINGER, (const char *)&ling, sizeof(struct linger)) == 0);res = true;}return res;}bool CServSocket::setTimeout(int option, int milliseconds){bool res = false;if(sockfd){struct timeval timeout;timeout.tv_sec = milliseconds/1000;timeout.tv_usec = (milliseconds%1000)*1000000;res = (setsockopt(sockfd, SOL_SOCKET, option, (const void*)&timeout, sizeof(timeout)) == 0);res = true;}return res;}bool CServSocket::setNonBlock(bool isnonsocket){bool res = false;if(sockfd){int oldfd = fcntl(sockfd, F_GETFL);res = (fcntl(sockfd, F_SETFL, oldfd | O_NONBLOCK) <0);res = true;}return res;}bool CServSocket::setNoDelay(bool nodelay){bool res = false;if(sockfd){int ndelay = nodelay?1:0;res = (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,(const void*)&ndelay, sizeof(ndelay)) == 0);res =true;}return res;}bool CServSocket::Send(char *sendbuf, int len){if(sockfd <0 || sendbuf==NULL || len < 0)return false;int dataleft = len, total = 0, ret =0;for(;dataleft >0;){ret = ::send(connsockfd, sendbuf+total, dataleft, 0);if(ret < 0){if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR){usleep(50000);ret = 0;}}total += ret;dataleft = len-total;}return total == len;}bool CServSocket::Recv(char *recvbuf, int len, int timeout){if(sockfd <0 || recvbuf==NULL || len < 0)return false;fd_set fds;struct timeval interval;interval.tv_sec = timeout;interval.tv_usec = 0;int recvlen = 0;for(;;){FD_ZERO(&fds);FD_SET(connsockfd, &fds);int res = ::select(connsockfd+1, &fds, NULL, NULL, &interval);if(res == 0)continue;if(res < 0){::close(connsockfd);connsockfd = -1;return false;}else{if(FD_ISSET(connsockfd, &fds)){recvlen = ::recv(connsockfd, recvbuf, len, 0);break;}}}return recvlen == len;}class CCliSocket{public:    CCliSocket();    virtual ~CCliSocket();bool Connect(const char* ip, int port);bool Send(char* sendbuf, int len);bool Recv(char* recvbuf, int len);private:bool Close();private:int clisockfd;};CCliSocket::CCliSocket(){if((clisockfd = ::socket(AF_INET, SOCK_STREAM, 0)) < 0){std::cout << "client socket err\n";}}CCliSocket::~CCliSocket(){if(!Close()){std::cout << "close err\n";}}bool CCliSocket::Close(){if(clisockfd < 0)return false;else{::close(clisockfd);clisockfd = -1;}return true;}bool CCliSocket::Connect(const char* ip, int port){if(ip==NULL || ip=="" || port < 0)return false;struct sockaddr_in sddr;sddr.sin_family = AF_INET;sddr.sin_addr.s_addr = inet_addr(ip);sddr.sin_port = htons(port);if(::connect(clisockfd, (struct sockaddr*)&sddr, sizeof(sddr)) < 0){std::cout << "connnect to server err\n";return false;}return true;}bool CCliSocket::Send(char* sendbuf, int len){int ret = 0;do{ret = ::send(clisockfd, sendbuf, len, 0);} while (ret < 0 && (errno == EAGAIN || errno == EINTR));    return ret == len; }bool CCliSocket::Recv(char* recvbuf, int len){int ret = 0;do{ret = ::recv(clisockfd, recvbuf, len, 0);} while (ret < 0 && (errno == EAGAIN || errno == EINTR));    return ret == len; }

測試:

TestServer.cpp

#include "CSocket.h"#include <string.h>int main(int argc, char *argv[]){    CServSocket servSocket;servSocket.Listen(9999);std::cout << "server start...\n";for(;;){if(!servSocket.Accept()){std::cout << "accept err\n";return -1;}if(servSocket.getAcceptSock() > 0){std::cout <<"client ("<< servSocket.getCliAddr() << ")\n";   char recvbuf[11];memset(recvbuf, 0, sizeof recvbuf);servSocket.Recv(recvbuf, 10, 0);std::cout << recvbuf<<std::endl;char sendbuf[256];memset(sendbuf,0, sizeof sendbuf);strcpy(sendbuf, "come from server");if(!servSocket.Send(sendbuf, 16)){std::cout << "send err\n";}}}    return 0;}

TestClient.cpp

#include "CSocket.h"#include <string.h>int main(int argc, char *argv[]){const char *ip = "192.168.149.79";CCliSocket cliSocket;cliSocket.Connect(ip, 9999);std::cout << "client connect server...\n";if(!cliSocket.Send("ABCDEFGHIJ", 10)){std::cout <<"send err\n";}char recvbuf[256];memset(recvbuf,0, sizeof recvbuf);if(!cliSocket.Recv(recvbuf, 16)){std::cout <<"recv err\n";}std::cout << recvbuf << std::endl;getchar();    return 0;}

編譯:

g++ -g -o testServer TestServer.cpp CSocket.h 

g++ -g -o testClient TestClient.cpp CSocket.h 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.