socket网络通信实现与优化
生活随笔
收集整理的这篇文章主要介绍了
socket网络通信实现与优化
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
多进程通信
进程通信方式
多进程通信的优化
服务端程序
#include "../_freecplus.h"CTcpServer TcpServer; // 创建服务端对象。 CLogFile logfile; // 程序退出时调用的函数void FathEXIT(int sig);void ChldEXIT(int sig); // 父进程退出时调用的函数void FathEXIT(int sig){if(sig>0){signal(sig,SIG_IGN);signal(SIGINT,SIG_IGN);signal(SIGTERM,SIG_IGN);printf("catch the signal %d\n",sig);}kill(0,15);//父进程退出,子进程也全部退出printf("父进程退出\n");exit(0);}void ChldEXIT(int sig) {if(sig>0){signal(sig,SIG_IGN);signal(SIGINT,SIG_IGN);signal(SIGTERM,SIG_IGN);}printf("子进程退出\n");exit(0); }int main(int argc,char *argv[]) {//关闭全部的信号logfile.Open("/tmp/log/demo1.log","a+");for(int i=0;i<100;i++){signal(i,SIG_IGN);}//设置信号,在shell下可用kill+进程号正常终止进程signal(SIGINT,FathEXIT);signal(SIGTERM,FathEXIT);signal(SIGCHLD,SIG_IGN);//忽略子进程退出的信号,避免产生僵尸进程if (TcpServer.InitServer(5005)==false) // 初始化TcpServer的通信端口。{// printf("TcpServer.InitServer(5005) failed.\n"); return -1;logfile.Write("TcpServer.InitServer(5005) failed.\n");return -1;} while(true) {if (TcpServer.Accept()==false) // 等待客户端连接。{printf("TcpServer.Accept() failed.\n"); return -1;}//printf("客户端(%s)已连接。\n",TcpServer.GetIP());logfile.Write("客户端(%s)已经连接。\n",TcpServer.GetIP()); if(fork()>0) {TcpServer.CloseClient();//父进程关闭多余的客户端连接上来的socketcontinue; }TcpServer.CloseListen();//子进程关闭监听的socket char strbuffer[1024]; // 存放数据的缓冲区。signal(SIGINT,ChldEXIT);signal(SIGTERM,ChldEXIT);while (true){memset(strbuffer,0,sizeof(strbuffer));if (TcpServer.Read(strbuffer,300)==false) break; // 接收客户端发过来的请求报文。//printf("接收:%s\n",strbuffer);logfile.Write("接收:%s\n",strbuffer);strcat(strbuffer,"ok"); // 在客户端的报文后加上"ok"。//printf("发送:%s\n",strbuffer);logfile.Write("发送:%s\n",strbuffer);if (TcpServer.Write(strbuffer)==false) break; // 向客户端回应报文。}//printf("客户端已断开。\n"); // 程序直接退出,析构函数会释放资源。logfile.Write("客户端已经断开。\n");exit(0); } }客户端程序
#include "../_freecplus.h"int main(int argc,char *argv[]) {CTcpClient TcpClient; // 创建客户端的对象。if (TcpClient.ConnectToServer("192.168.74.10",5005)==false) // 向服务端发起连接请求。{printf("TcpClient.ConnectToServer(\"172.16.0.15\",5858) failed.\n"); return -1;}char strbuffer[1024]; // 存放数据的缓冲区。printf("pid=%d\n",getpid());for (int ii=0;ii<20;ii++) // 利用循环,与服务端进行5次交互。{memset(strbuffer,0,sizeof(strbuffer));snprintf(strbuffer,50,"pid=%d:这是第%d个超级女生,编号%03d。",getpid(),ii+1,ii+1);printf("发送:%s\n",strbuffer);if (TcpClient.Write(strbuffer)==false) break; // 向服务端发送请求报文。memset(strbuffer,0,sizeof(strbuffer));if (TcpClient.Read(strbuffer,20)==false) break; // 接收服务端的回应报文。printf("接收:%s\n",strbuffer);sleep(1);}// 程序直接退出,析构函数会释放资源。 }运行窗口
服务端业务主体代码
客户端主体代码
while(1){if(biz001()==false);break;} // 身份验证。 bool biz001() {char strbuffer[1024]; // 存放数据的缓冲区。memset(strbuffer,0,sizeof(strbuffer)); char name[10]; memset(name,0,sizeof(name)); char password[10]; memset(password,0,sizeof(password)); printf("请输入用户名:"); scanf("%s",name); printf("请输入密码:"); scanf("%s",password);snprintf(strbuffer,1000,"<bizcode>1</bizcode><username>%s</username><password>%s</password>",name,password);printf("发送:%s\n",strbuffer);if (TcpClient.Write(strbuffer)==false) return false; // 向服务端发送请求报文。memset(strbuffer,0,sizeof(strbuffer));if (TcpClient.Read(strbuffer,20)==false) return false; // 接收服务端的回应报文。printf("接收:%s\n",strbuffer);int iretcode=-1;GetXMLBuffer(strbuffer,"retcode",&iretcode);if (iretcode==0) { printf("身份验证成功。\n"); return true; }printf("身份验证失败。\n");return false; }多线程通信
多线程服务程序退出
思路
需要注意的点:收到2,15信号,执行信号函数取消同样会调用线程清理函数,我这里usleep(200),即可发现这个问题
服务端代码
#include "../_freecplus.h" void* pthmain(void* arg); void mainexit(int sig); vector<pthread_t>vpthid; CTcpServer TcpServer; // 创建服务端对象。 int main(int argc,char *argv[]) { signal(2,mainexit);signal(5,mainexit); if (TcpServer.InitServer(5005)==false) // 初始化TcpServer的通信端口。{ printf("TcpServer.InitServer(5858) failed.\n"); return -1;}while(true){ if (TcpServer.Accept()==false) // 等待客户端连接。{ printf("TcpServer.Accept() failed.\n"); return -1;}printf("客户端(%s)已连接。\n",TcpServer.GetIP());pthread_t pthid1;if(pthread_create(&pthid1,NULL,pthmain,(void*)(long)TcpServer.m_connfd)!=0){printf("creat pthid1 fail\n");return -1;}vpthid.push_back(pthid1);}return 0; } //2,15信号处理函数 void mainexit(int sig) {printf("mainexit begin.\n");TcpServer.CloseListen();//关闭监听的socketfor(int i=0;i<vpthid.size();i++){printf("cancel %ld\n",vpthid[i]);pthread_cancel(vpthid[i]);//取消全部的线程}printf("mainexit end.\n");usleep(20);exit(0); } //设置线程清理函数 void pthmainexit(void* arg) {printf("线程清理函数开始。\n");close((int)(long)arg);//关闭线程连接的socket for(int i=0;i<vpthid.size();i++){if(vpthid[i]==pthread_self()){vpthid.erase(vpthid.begin()+i);}}printf("线程清理函数结束.\n"); } void* pthmain(void* arg) {pthread_cleanup_push(pthmainexit,arg);//注册线程清理函数pthread_detach(pthread_self());pthread_setcanceltype(PTHREAD_CANCEL_DISABLE,NULL);int sockfd=(int)(long)(arg);while (true){char strbuffer[1024]; // 存放数据的缓冲区。int buflen=0;memset(strbuffer,0,sizeof(strbuffer));if (TcpRead(sockfd,strbuffer,&buflen,300)==false) break; // 接收客户端发过来的请求报文。printf("接收:%s\n",strbuffer);strcat(strbuffer,"ok"); // 在客户端的报文后加上"ok"。printf("发送:%s\n",strbuffer);if (TcpWrite(sockfd,strbuffer,buflen)==false) break; // 向客户端回应报文。}printf("客户端已断开。\n");pthread_cleanup_pop(1);//执行线程清理函数 }运行窗口
性能测试
服务端并发量测试
- 实验环境:两台独立的虚拟机,客户端给服务端只发送心跳报文,测试1000台客户端连接服务端后,服务端均为多进程,查看服务端内存和cpu的变化情况
实验前
cpu的运行情况:
内存的消耗情况:
实验后
服务端运行的进程数
cpu的运行情况:
内存的消耗情况:
服务端业务性能测试
- 实验环境:两台独立的虚拟机,客户端给服务端只发送心跳报文,测试100台客户端同时连接服务端后,服务端均为多进程,查看服务端cpu的变化情况,以及每秒接受的信息量。
== 客户端业务==
服务端消耗内存
之前:
之后:
结论:消耗内存大概为16M
服务端cpu情况:
服务端每秒接收的数据量:
多进程/多线程服务端性能
多线程:
内存消耗对比:
之前:
之后:
cpu消耗情况:
多线程1s处理报文的数量:
结论:1.连接相同客户端,处理相同的业务,多线程消耗内存为7M,多进程为16M
2.多进程cpu剩余30%,多进程剩余20%
3.多进程和多线程1s处理的报文数基本相同,都为8000多。
客户端业务响应时间
环境:两台centos7局域网上客户端在不同阶段的测试响应时间
1.客户端
2.客户端给服务端发送心跳报文,此时服务端闲时,计算从发送到接受的耗时
3.客户端给服务端发送心跳报文,此时服务端忙时,计算从发送到接受的耗时
总结
以上是生活随笔为你收集整理的socket网络通信实现与优化的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 【谷歌地图--PlacesSDK集成】
- 下一篇: redis实现分布式锁(乞丐版)