简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器相关的知识,希望对你有一定的参考价值。
1 服务器代码 Linux eclipse C++
1 //============================================================================ 2 // Name : epollServer.cpp 3 // Author : fangjunmin 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C++, Ansi-style 7 //============================================================================ 8 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 #include <iostream> 12 #include <stdio.h> 13 #include <arpa/inet.h> 14 #include <errno.h> 15 #include <sys/epoll.h> 16 #include <map> 17 #include <vector> 18 #include <memory.h> 19 #include "encode.h" 20 #include <stddef.h> 21 22 using namespace std; 23 24 int g_epfd = -1; 25 int g_listen_fd = -1; 26 u_short g_listen_port = 8000; 27 28 29 typedef map<int, int> mapClient ; 30 typedef map<int, int>::iterator itmapClient ; 31 typedef map<int, int>::const_iterator citmapClient ; 32 33 typedef vector<int> vecClient ; 34 typedef vecClient::iterator itvecClient ; 35 typedef vecClient::const_iterator citvecClient ; 36 37 mapClient g_mapClient; 38 vecClient g_vecCLient; 39 40 void InitListen(); 41 void StartEpoll(); 42 void BoardCast(const char* msg, long int nLen); 43 void removeFd(int fd); 44 45 int main() 46 { 47 cout << "!!!Hello epoll!!!" << endl; // prints !!!Hello epoll!!! 48 49 InitListen(); 50 StartEpoll(); 51 return 0; 52 } 53 54 void InitListen() 55 { 56 g_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 57 if (g_listen_fd == -1) 58 { 59 return ; 60 } 61 62 struct sockaddr_in sin; 63 //bzero(&sin, sizeof(struct sockaddr_in)); 64 sin.sin_family = AF_INET; 65 sin.sin_addr.s_addr = INADDR_ANY; 66 sin.sin_port = htons(g_listen_port); 67 68 if (bind(g_listen_fd, (struct sockaddr *) &sin, sizeof(struct sockaddr)) != 0) 69 { 70 printf("bind error: %d\n", errno); 71 return ; 72 } 73 74 if (listen(g_listen_fd, 5) != 0) 75 { 76 printf("listen error!\n"); 77 return ; 78 } 79 } 80 81 void StartEpoll() 82 { 83 int nSize = 5; 84 g_epfd = epoll_create(nSize); 85 86 epoll_event ev; 87 ev.data.fd=g_listen_fd; 88 ev.events = EPOLLIN | EPOLLET | EPOLLOUT; 89 int nAddResult = epoll_ctl(g_epfd ,EPOLL_CTL_ADD, g_listen_fd ,&ev); //将新的fd添加到epoll的监听队列中 90 if (nAddResult == -1) 91 { 92 printf ("epoll_ctl error\n"); 93 return ; 94 } 95 96 97 while(true) 98 { 99 epoll_event events[nSize + 1]; 100 int nfds = epoll_wait(g_epfd, events, 20,0); 101 for(int i=0; i<nfds; ++i) 102 { 103 printf("event num is: %d\n", nfds); 104 if(events[i].data.fd == g_listen_fd) //有新的连接 105 { 106 sockaddr_in clientaddr; 107 unsigned int clilen = sizeof(clientaddr); 108 int connfd = accept(g_listen_fd, (sockaddr *)&clientaddr, &clilen); //accept这个连接 109 printf("new connection! %d\n", connfd); 110 111 epoll_event event; 112 event.data.fd=connfd; 113 event.events = EPOLLIN | EPOLLET | EPOLLOUT | EPOLLHUP; 114 epoll_ctl(g_epfd,EPOLL_CTL_ADD,connfd,&event); //将新的fd添加到epoll的监听队列中 115 116 g_vecCLient.push_back(connfd); 117 } 118 119 else if( events[i].events & EPOLLIN ) //接收到数据,读socket 120 { 121 char szBuf[1024] = {0}; 122 int nRecvNum = recv(events[i].data.fd, szBuf, 1024, 0); //读 123 124 125 char szDest[1024] = {0}; 126 size_t nOutLen = 1024 ; 127 GB2312ToUtf8(szBuf, nRecvNum, szDest, nOutLen); 128 printf("recv size :%d, concent:%s\n", nRecvNum, szBuf); 129 printf("after conv size :%d, concent:%s\n", nOutLen , szDest); 130 131 if(nRecvNum > 0) 132 { 133 BoardCast(szBuf, nRecvNum); 134 } 135 else if(nRecvNum == -1) 136 { 137 perror(NULL); 138 removeFd(events[i].data.fd); 139 } 140 141 // ev.data.ptr = md; //md为自定义类型,添加数据 142 // ev.events=EPOLLOUT|EPOLLET; 143 // epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改标识符,等待下一个循环时发送数据,异步处理的精髓 144 } 145 else if(events[i].events & EPOLLOUT) //有数据待发送,写socket 146 { 147 printf("EPOLLOUT\n" ); 148 // struct myepoll_data* md = (myepoll_data*)events[i].data.ptr; //取数据 149 // sockfd = md->fd; 150 // send( sockfd, md->ptr, strlen((char*)md->ptr), 0 ); //发送数据 151 // ev.data.fd=sockfd; 152 // ev.events=EPOLLIN|EPOLLET; 153 // epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改标识符,等待下一个循环时接收数据 154 } 155 else if(events[i].events & EPOLLHUP) //socket disconnect 156 { 157 printf("socket disconnect socketid:%d\n", events[i].data.fd); 158 removeFd(events[i].data.fd); 159 } 160 else 161 { 162 //其他的处理 163 } 164 } 165 } 166 } 167 168 void BoardCast(const char* msg, long int nLen) 169 { 170 for(citvecClient cit = g_vecCLient.begin(); cit != g_vecCLient.end(); cit++) 171 { 172 int nClientFd = *cit; 173 int nSendLen = send(nClientFd, (const void* )msg , nLen, 0); 174 printf("socket nSendLen:%d\n", nSendLen); 175 } 176 177 } 178 179 void removeFd(int fd) 180 { 181 epoll_ctl(g_epfd,EPOLL_CTL_DEL,fd, NULL); //delete socket in epoll 182 for(itvecClient it = g_vecCLient.begin(); it != g_vecCLient.end(); it++) 183 { 184 if(fd == *it) 185 { 186 g_vecCLient.erase(it); 187 return; 188 } 189 } 190 }
2 Windows下的客户端代码 Windows、visual studio 、C++
主线程 读线程 写线程
1 #include "stdio.h" 2 #include <WinSock2.h> 3 #include "cInitSock.h" 4 #include <string> 5 #pragma comment(lib,"WS2_32") 6 7 8 using namespace std; 9 //struct stMsg 10 //{ 11 // int sCmdID; 12 // int sLen; 13 // int nValue; 14 // string strContent; 15 // 16 // stMsg() 17 // { 18 // sCmdID = 0; 19 // sLen = 0; 20 // nValue = 0; 21 // strContent = ""; 22 // } 23 //}; 24 25 26 27 char g_szIp[64] = "192.168.10.32"; 28 short g_port = 8000; 29 SOCKET g_sock; 30 31 32 void ReadHandle(); 33 void WriteHandle(); 34 CRITICAL_SECTION g_cs; 35 36 static int s_na = 0; 37 38 39 void main() 40 { 41 cInitSock initSock; 42 InitializeCriticalSection(&g_cs); 43 g_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 44 45 sockaddr_in sockAddr; 46 memset(&sockAddr,0,sizeof(sockAddr)); 47 48 sockAddr.sin_family = AF_INET; 49 sockAddr.sin_addr.S_un.S_addr = inet_addr(g_szIp); 50 sockAddr.sin_port = htons((u_short)g_port); 51 int nRestle = 0; 52 nRestle= connect(g_sock, (sockaddr *)&sockAddr, sizeof(sockAddr) ); 53 54 DWORD dErr = GetLastError(); 55 if (nRestle != 0 ) 56 { 57 printf("连接服务器失败 \n"); 58 return; 59 } 60 printf("connect success \n"); 61 62 int nReadThreadID; 63 int nWriteThreadID; 64 CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ReadHandle, 0, 0, (LPDWORD)&nReadThreadID); 65 CreateThread(0, 0, (LPTHREAD_START_ROUTINE) WriteHandle, 0, 0, (LPDWORD)&nWriteThreadID); 66 67 printf("客户端开启成功\n"); 68 while(1) 69 { 70 ; 71 } 72 73 } 74 75 76 void ReadHandle() 77 { 78 char buf[1024] = ""; 79 int buflen = 0; 80 81 while (1) 82 { 83 memset(buf, 0, 1024); 84 buflen = recv(g_sock, buf, 1024, 0); 85 if ( buflen ) 86 { 87 EnterCriticalSection((LPCRITICAL_SECTION)&g_cs); 88 printf("recv msg : %s,msgSiez:%d\n", buf, buflen); 89 LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs); 90 } 91 } 92 } 93 94 void WriteHandle() 95 { 96 char buf[1024] = ""; 97 int buflen = 0; 98 99 while (1) 100 { 101 gets_s(buf); 102 //printf("the gets buf is:%s:end\n", buf); 103 buflen = send(g_sock, (const char* )&buf, strlen(buf), 0); 104 if ( buflen > 0) 105 { 106 EnterCriticalSection((LPCRITICAL_SECTION)&g_cs); 107 printf("send msg : %s,msgSiez:%d\n", buf, buflen); 108 LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs); 109 } 110 if (buflen == -1) 111 { 112 EnterCriticalSection((LPCRITICAL_SECTION)&g_cs); 113 printf("send msg error: %s\n", buf); 114 LeaveCriticalSection((LPCRITICAL_SECTION)&g_cs); 115 } 116 } 117 } 118
以上是关于简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器的主要内容,如果未能解决你的问题,请参考以下文章
python实现简单聊天应用 python群聊和点对点均实现