简单通讯聊天 群聊功能 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群聊和点对点均实现

使用SpringBoot开发群聊应用

iOS-Senior21-环信

ThinkPHP微的H5聊天室即时通讯系统APP源码分享

javascript基于websocketnodejsuniapp的聊天室

javascript基于websocketnodejsuniapp的聊天室