服务端
#include#include #include //系统调用的接口 #include //网络有关 #include //linux相关基本数据类型 #include #include class CTcpServer{ public: int m_listenfd; //监听socket int m_clientfd; // 监听之后接受连接的socket CTcpServer(){ m_listenfd = 0; //初始化为0 } ~CTcpServer(){ close(m_listenfd); close(m_clientfd); } bool InitServer(int port){ m_listenfd = socket(AF_INET, SOCK_STREAM, 0);//第三个表示协议,0表示默认tcp协议 struct sockaddr_in Serveraddr; //先初始化再赋值 memset(&Serveraddr, 0, sizeof(Serveraddr)); Serveraddr.sin_family = AF_INET; Serveraddr.sin_addr.s_addr = htons(INADDR_ANY); Serveraddr.sin_port = htons(port); if(bind(m_listenfd, (struct sockaddr *)&Serveraddr, sizeof(Serveraddr) ) != 0){ printf("绑定失败n"); close(m_listenfd); return false; } if(listen(m_listenfd, 5) !=0){ printf("监听失败n"); close(m_listenfd); return false; } return true; } bool Accept(){ struct sockaddr_in clientaddr; //if((m_clientfd = accept(m_listenfd, (struct sockaddr *)&clientaddr, sizeof(clientaddr))) <= 0) if((m_clientfd = accept(m_listenfd, 0, 0)) <= 0) //为什么是0,0 return false; return true; } void CloseClient(){ close(m_clientfd); return ; } void CloseListen(){ close(m_listenfd); return ; } }; CTcpServer TcpServer; int main(){ if(TcpServer.InitServer(5001) == false){ printf("服务端初始化失败n"); return -1; } while(1){ if(TcpServer.Accept() == false) continue; int pid = fork(); if(pid != 0){ TcpServer.CloseClient(); continue; } else{ TcpServer.CloseListen(); printf("客户端已连接n"); char buffer[1024]; while(1){ memset(buffer, 0, sizeof(buffer));//表示动态分配内存的大小, 比如指针指向的数组是4 if(recv(TcpServer.m_clientfd ,buffer, sizeof(buffer), 0 ) <= 0) break;//实际的长度 printf("接收:%sn", buffer); strcpy(buffer, "OK"); if(send(TcpServer.m_clientfd ,buffer, strlen(buffer), 0) <= 0) break; printf("发送:%sn", buffer); } } printf("客户端已经断开n"); return 0; } }
客户端
#include#include #include #include #include #include #include // TCP客户端类 class CTcpClient { public: int m_sockfd; CTcpClient(); // 向服务器发起连接,serverip-服务端ip,port通信端口 bool ConnectToServer(const char *serverip,const int port); // 向对端发送报文 int Send(const void *buf,const int buflen); // 接收对端的报文 int Recv(void *buf,const int buflen); ~CTcpClient(); }; int main() { CTcpClient TcpClient; // 向服务器发起连接请求 if (TcpClient.ConnectToServer("192.168.23.128",5001)==false) { printf("TcpClient.ConnectToServer("172.16.0.15",5051) failed,exit...n"); return -1; } char strbuffer[1024]; for (int ii=0;ii<5;ii++) { memset(strbuffer,0,sizeof(strbuffer)); sprintf(strbuffer,"这是第%d个超级女生,编号%03d。",ii+1,ii+1); if (TcpClient.Send(strbuffer,strlen(strbuffer))<=0) break; printf("发送:%sn",strbuffer); memset(strbuffer,0,sizeof(strbuffer)); if (TcpClient.Recv(strbuffer,sizeof(strbuffer))<=0) break; printf("接收:%sn",strbuffer); sleep(1); // sleep一秒,方便观察程序的运行。 } } CTcpClient::CTcpClient() { m_sockfd=0; // 构造函数初始化m_sockfd } CTcpClient::~CTcpClient() { if (m_sockfd!=0) close(m_sockfd); // 析构函数关闭m_sockfd } // 向服务器发起连接,serverip-服务端ip,port通信端口 bool CTcpClient::ConnectToServer(const char *serverip,const int port) { m_sockfd = socket(AF_INET,SOCK_STREAM,0); // 创建客户端的socket struct hostent* h; // ip地址信息的数据结构 转化成网络字节序 if ( (h=gethostbyname(serverip))==0 ) { close(m_sockfd); m_sockfd=0; return false; } // 把服务器的地址和端口转换为数据结构 struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // 向服务器发起连接请求 if (connect(m_sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))!=0) { close(m_sockfd); m_sockfd=0; return false; } return true; } int CTcpClient::Send(const void *buf,const int buflen) { return send(m_sockfd,buf,buflen,0); } int CTcpClient::Recv(void *buf,const int buflen) { return recv(m_sockfd,buf,buflen,0); }
运行结果:
多进程和单进程的区别在于服务端的处理,多进程可以同时接受很多个客户端的连接并通信。
这里使用类来封装socket,他的作用是
1)把数据初始化的代码放在构造函数中;
2)把关闭socket等释放资源的代码放在析构函数中;
3)把socket定义为类的成员变量,类外部的代码根本看不到socket。
4)代码更简洁,更安全(析构函数自动调用关闭socket,释放资源)。



