c++实现封装socket2
2015-11-24 11:10
323 查看
编程实例:
CSocket.h
TestServer.h
TestClient.h
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 CSocket { public: CSocket(); virtual ~CSocket(); std::string getLocalAddr(); std::string getCliIp(); int getSockfd() { return sockfd;} bool Close(); bool Connect(); bool Send(char* sendbuf, int len); bool Recv(char* recvbuf, int len, int timeout); 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); bool setUp(int sockfd, struct sockaddr_in* addr); bool setAddr(const char* addr, int port); protected: int sockfd; char ip[20]; struct sockaddr_in sockAddr; CSocket(const CSocket&); CSocket& operator=(const CSocket&); }; CSocket::CSocket() { sockfd = ::socket(AF_INET, SOCK_STREAM, 0); if(sockfd <= 0) { std::cout << "create socket err\n"; } memset(ip, 0, sizeof(ip)); } CSocket::~CSocket() { Close(); } bool CSocket::Close() { if(sockfd > 0) close(sockfd); else return false; sockfd = -1; return true; } std::string CSocket::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 CSocket::getCliIp() { char cliIp[16]; struct sockaddr_in cliAddr; 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; } bool CSocket::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 CSocket::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 CSocket::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 CSocket::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 CSocket::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 CSocket::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(sockfd, 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 CSocket::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(sockfd, &fds); int res = ::select(sockfd+1, &fds, NULL, NULL, &interval); if(res == 0) continue; if(res < 0) { ::close(sockfd); sockfd = -1; return false; } else { if(FD_ISSET(sockfd, &fds)) { recvlen = ::recv(sockfd, recvbuf, len, 0); break; } } } return recvlen == len; } bool CSocket::setUp(int fd, struct sockaddr_in* addr) { Close(); this->sockfd = fd; memcpy(&sockAddr, addr, sizeof(sockAddr)); return true; } bool CSocket::Connect() { if(sockfd < 0) { return false; } return (::connect(sockfd, (struct sockaddr*)&sockAddr, sizeof(sockAddr))); } //tcp server class CServSocket : public CSocket { public: CServSocket(); virtual ~CServSocket(); CSocket* Accept(); bool Listen(int port); private: bool Close(); private: }; CServSocket::CServSocket():CSocket::CSocket() {} CServSocket::~CServSocket() { if(!Close()) { std::cout << "close err\n"; } } bool CServSocket::Close() { CSocket::Close(); return true; } bool CServSocket::Listen(int port) { if(port < 0) { std::cout <<"the port err\n"; return false; } if(sockfd < 0) { return false; } setAddr(getLocalAddr().c_str(), 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*)&sockAddr, sizeof(sockAddr)) < 0) { std::cout << "bind err\n"; return false; } if(::listen(sockfd, 0) < 0) { std::cout << "listen err\n"; return false; } return true; } CSocket* CServSocket::Accept() { CSocket* connSocket; struct sockaddr_in addr; socklen_t len = sizeof(addr); int connsockfd = -1; if((connsockfd = ::accept(sockfd, (struct sockaddr*)&addr, &len)) <0) { return false; } connSocket = new CSocket(); connSocket->setUp(connsockfd, &addr); return connSocket; } bool CSocket::setAddr(const char* addr, int port) { memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(port); if(addr==NULL || strlen(addr)==0) { sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); return true; } else { const char* p = addr; char c; bool isIp = true; while((c=*p++)&& (c !='\0')) { if((c !='.') && !(c>='0' && c<='9')) { isIp = false; break; } } if(isIp) { sockAddr.sin_addr.s_addr = inet_addr(addr); return true; } else { struct hostent *host = gethostbyname(addr); if(host != NULL) { memcpy(&(sockAddr.sin_addr), *(host->h_addr_list), sizeof(struct in_addr)); } } } return false; } //tcp client 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.h
#include "CSocket.h" #include <string.h> int main(int argc, char *argv[]) { CServSocket servSocket; CSocket *socket; if(!servSocket.Listen(9999)) { std::cout << "listen err\n"; } for(;;) { if(!(socket = servSocket.Accept())) { std::cout << "accept err\n"; return -1; } if(socket->getSockfd()> 0) { std::cout <<"client ("<< socket->getCliIp() << ")\n"; char recvbuf[11]; memset(recvbuf, 0, sizeof recvbuf); socket->Recv(recvbuf, 10, 0); std::cout << recvbuf<<std::endl; char sendbuf[256]; memset(sendbuf,0, sizeof sendbuf); strcpy(sendbuf, "come from server"); if(!socket->Send(sendbuf, 16)) { std::cout << "send err\n"; } } } return 0; }
TestClient.h
#include "CSocket.h" #include <string.h> int main(int argc, char *argv[]) { const char *ip = "192.168.149.79"; CSocket *socket = new CSocket(); socket->setAddr(ip, 9999); socket->Connect(); std::cout << "client connect server...\n"; if(!socket->Send("ABCDEFGHIJ", 10)) { std::cout <<"send err\n"; } char recvbuf[256]; memset(recvbuf,0, sizeof recvbuf); if(!socket->Recv(recvbuf, 16, 0)) { std::cout <<"recv err\n"; } std::cout << recvbuf << std::endl; getchar(); return 0; }
相关文章推荐
- 顺序队的基本操作(C++完整代码)
- C语言常见命名规范
- C++学习中关于cout遇到的一个小问题
- c++调试重要武器GetLastError
- C语言 side effect和sequence point
- vector 中生成一大批线程并等待完成
- 【转】使用C语言实现MD5消息摘要算法
- 【C语言】 浅谈指针
- c\c++ codeblocks编译常见错误
- C\C++代码优化的27个建议
- 深入理解C语言的define和内联函数
- 详解C/C++ 编译 g++ gcc 的区别
- C++二叉搜索树的实现
- 遇到的c/c++问题汇总
- C++ 学习 (static_cast、 volatile 等)
- C++ 中new char[]()和C++ 中new char[]的区别
- C语言中的内联函数(inline)与宏定义(#define)详细解析
- 冒泡排序和选择排序C++实现
- C++进行CGI的WEB编程
- win编程实践(4)【c++】- 多维数组指针