Linux下的基于Pthread的多线程Socket编程

程序设计

服务端的程序的设计主要是一个主线程首先调用Socket相关的函数socket,bind, listen在建立服务端的Socket之后,等待Accept上面,如果有新的客户端连接上来,则对于每一个客户端新建一个线程。在每一个客户端的线程中,其接收客户端发送的指令然后返回相关的信息,主线程Socket中默认的Accpet默认是阻塞的,这里采用了Linux中函数fctnl将其设置成非阻塞。除了客户端对应的线程和主线程之外,服务端还存在一个服务端的控制线程,其主要是接受服务端的命令,诸如退出,断开连接等等,对服务端的程序进行控制。

客户端的程序为一个阻塞的循环,接受用户的输入然后解析命令进行相关的操作,诸如连接服务端,发送数据等等操作

服务端实现细节

服务端的程序主要包括主线程接受客户端请求响应建立客户端对应线程,客户端命令执行,服务端主要控制模块。

主线程

首先建立服务端Socket连接,其过程如下:

  • 首先调用socket函数建立一个socket,其中传入的参数AF_INET参数表示其采用TCP协议,并且调用Linux系统提供的fcntl函数设置这个socket为非阻塞。
  • 然后初始化服务的地址,保护监听的IP(这里设置的监听服务器端所有的网卡),设置相应的端口以及协议类型(TCP),调用bind函数将其和前面的建立的socket绑定。
  • 设置该socket开始监听,这主要对应TCP连接上面的第一次握手,将TCP第一次握手成功的放在队列(SYN队列)中,其中传入的参数BACKLOG为Socket中队列的长度。
  • 然后调用Accept函数进行接收客户端的请求,其主要是从TCP上次握手成功的Accept队列中将客户端信息去除进行处理(此部分代码后面解释)。

最后服务端的主要是在一个循环中,其中最前面的serverExit主要是为了交互需要,后面会详细介绍。服务端调用Accept函数进行接收一个客户端的信息,如果存在连接上的客户端,则为其分配一个线程位置,然后调用pthread_create创建一个线程,并且将该客户端的信息参数传入线程。这里采用一个结构体的方式记录了客户端的相关信息,包括客户端IP,端口号,编号,是否连接等等。

这里为了防止服务器的无限的创建线程,设置了最大同时在线的客户端数目(MAXCONN),如果新连接上的客户端发现已经操作上线,那么该主线程就会睡眠,其等待在了一个客户端断开连接的信号量上面,如果有客户端断开连接,则主线程被唤醒,接受该客户端的连接。

需要注意的是这里涉及到很多的多线程的操作,很有可能发生数据冲突,需要很好使用pthread中的互斥锁防止发生数据冲突。

客户端服务线程

其主要是阻塞的接受客户端发送上来的命令,然后解析命令,对应每个命令进行不同的操作,将结果通过send函数发送给对应的客户端。这里主要实现了disconn断开连接,name返回客户端,list返回所有连接的客户端的信息(IP,端口,编号等等),send向别的客户端发送数据。
对于name和time命令只要将数据以字符串的形式发送给对应的客户端即可,而对于disconn命令,需要发送一个断开的信号,使得等待在这个信号量上的客户端能够连接上服务端,对于send命令需要根据发送的地址获取到目的的客户端信息,相对应的客户端发送相关的消息。服务端的程序另一个需要的是需要进行错误处理,诸如客户端的命令错误,格式错误,网络错误等等异常情况,其需要进行相应的报错,并且提供给客户端或者服务端相应的错误信息。
这里主要注意的是发送的数据需要指定数据的长度,而采用C的strlen指定的并不包括字符串最后的‘\0’,因此其不会发送出去。这里有两种解决方案,一种是接收方在数据的最后加上’\0’或者发送的时候将’\0’一同发送出去。

服务端控制线程

服务端控制程序主要提供了一些命令给服务端可以对于服务端连接的客户端以及自身退出。这里主要实现了exit退出服务端,list列出所有连接的客户端信息,kill关闭某个客户端命令。其中exit命令为退出客户端,其主要是将一个退出退出标志位设置成1,然后主线程判断该标志位为1的时候会关闭所有的客户端,并且取消所有的客户端线程以及服务端程序线程,然后自身退出。对于list命令其和服务端发送的list指令实现相同,kill命令主要是关闭对于对应的客户端的socket,然后取消其对应的线程。

  1 #include <sys/types.h>
  2 #include <sys/socket.h>
  3 #include <netinet/in.h>
  4 #include <arpa/inet.h>
  5 #include <sys/time.h>
  6 #include <stdio.h>
  7 #include <errno.h>
  8 #include <string.h>
  9 #include <pthread.h>
 10 #include <stdlib.h>
 11 #include <fcntl.h>
 12 #include <unistd.h>
 13
 14 #define PORT  8888
 15 #define BACKLOG 10
 16 #define MAXCONN 100
 17 #define BUFFSIZE 1024
 18
 19 typedef unsigned char BYTE;
 20 typedef struct ClientInfo
 21 {
 22     struct sockaddr_in addr;
 23     int clientfd;
 24     int isConn;
 25     int index;
 26 } ClientInfo;
 27
 28 pthread_mutex_t activeConnMutex;
 29 pthread_mutex_t clientsMutex[MAXCONN];
 30 pthread_cond_t connDis;
 31
 32 pthread_t threadID[MAXCONN];
 33 pthread_t serverManagerID;
 34
 35 ClientInfo clients[MAXCONN];
 36
 37 int serverExit = 0;
 38
 39 /*@brief Transform the all upper case
 40 *
 41 */
 42 void tolowerString(char *s)
 43 {
 44     int i=0;
 45     while(i < strlen(s))
 46     {
 47         s[i] = tolower(s[i]);
 48         ++i;
 49     }
 50 }
 51
 52 void listAll(char *all)
 53 {
 54     int i=0, len = 0;
 55     len += sprintf(all+len, "Index   \t\tIP Address   \t\tPort\n");
 56     for(;i<MAXCONN;++i)
 57     {
 58         pthread_mutex_lock(&clientsMutex[i]);
 59         if(clients[i].isConn)
 60             len += sprintf(all+len, "%.8d\t\t%s\t\t%d\n",clients[i].index, inet_ntoa(clients[i].addr.sin_addr), clients[i].addr.sin_port);
 61         pthread_mutex_unlock(&clientsMutex[i]);
 62     }
 63 }
 64
 65 void clientManager(void* argv)
 66 {
 67     ClientInfo *client = (ClientInfo *)(argv);
 68
 69     BYTE buff[BUFFSIZE];
 70     int recvbytes;
 71
 72     int i=0;
 73     int clientfd = client->clientfd;
 74     struct sockaddr_in addr = client->addr;
 75     int isConn = client->isConn;
 76     int clientIndex = client->index;
 77
 78     while((recvbytes = recv(clientfd, buff, BUFFSIZE, 0)) != -1)
 79     {
 80      //   buff[recvbytes] = ‘\0‘;
 81         tolowerString(buff);    //case-insensitive
 82
 83         char cmd[100];
 84         if((sscanf(buff, "%s", cmd)) == -1)    //command error
 85         {
 86            char err[100];
 87            if(send(clientfd, err, strlen(err)+1, 0) == -1)
 88            {
 89                strcpy(err, "Error command and please enter again!\n");
 90                fprintf(stdout, "%d sends an eroor command\n", clientfd);
 91                break;
 92            }
 93         }
 94         else
 95         {
 96             char msg[BUFFSIZE]; //The message content
 97             int dest = clientIndex; //message destination
 98             int isMsg = 0;              //any message needed to send
 99             if(strcmp(cmd, "disconn") == 0)
100             {
101                 pthread_cond_signal(&connDis);  //send a disconnetion signal and the waiting client can get response
102                 break;
103             }
104             else if(strcmp(cmd, "time") == 0)
105             {
106                 time_t now;
107                 struct tm *timenow;
108                 time(&now);
109                 timenow = localtime(&now);
110                 strcpy(msg, asctime(timenow));
111                 isMsg = 1;
112             }
113             else if(strcmp(cmd, "name") == 0)
114             {
115                 strcpy(msg, "MACHINE NAME");
116                 isMsg = 1;
117             }
118             else if(strcmp(cmd, "list") == 0)
119             {
120                 listAll(msg);
121                 isMsg = 1;
122             }
123             else if(strcmp(cmd, "send") == 0)
124             {
125
126                 if(sscanf(buff+strlen(cmd)+1, "%d%s", &dest, msg)==-1 || dest >= MAXCONN)
127                 {
128                     char err[100];
129                     strcpy(err, "Destination ID error and please use list to check and enter again!\n");
130                     fprintf(stderr, "Close %d client eroor: %s(errno: %d)\n", clientfd, strerror(errno), errno);
131                     break;
132                 }
133                 fprintf(stdout, "%d %s\n", dest, msg);
134                 isMsg = 1;
135             }
136             else
137             {
138                 char err[100];
139                 strcpy(err, "Unknown command and please enter again!\n");
140                 fprintf(stderr, "Send to %d message eroor: %s(errno: %d)\n", clientfd, strerror(errno), errno);
141                 break;
142             }
143
144
145             if(isMsg)
146             {
147                 pthread_mutex_lock(&clientsMutex[dest]);
148                 if(clients[dest].isConn == 0)
149                 {
150                     sprintf(msg, "The destination is disconneted!");
151                     dest = clientIndex;
152                 }
153
154                 if(send(clients[dest].clientfd, msg, strlen(msg)+1, 0) == -1)
155                 {
156                     fprintf(stderr, "Send to %d message eroor: %s(errno: %d)\n", clientfd, strerror(errno), errno);
157                     pthread_mutex_unlock(&clientsMutex[dest]);
158                     break;
159                 }
160                 printf("send successfully!\n");
161                 pthread_mutex_unlock(&clientsMutex[dest]);
162             }
163         }  //end else
164     }   //end while
165
166     pthread_mutex_lock(&clientsMutex[clientIndex]);
167     client->isConn = 0;
168     pthread_mutex_unlock(&clientsMutex[clientIndex]);
169
170     if(close(clientfd) == -1)
171         fprintf(stderr, "Close %d client eroor: %s(errno: %d)\n", clientfd, strerror(errno), errno);
172     fprintf(stderr, "Client %d connetion is closed\n", clientfd);
173
174     pthread_exit(NULL);
175 }
176
177 void serverManager(void* argv)
178 {
179     while(1)
180     {
181         char cmd[100];
182         scanf("%s", cmd);
183         tolowerString(cmd);
184         if(strcmp(cmd, "exit") == 0)
185             serverExit = 1;
186         else if(strcmp(cmd, "list") == 0)
187         {
188             char buff[BUFFSIZE];
189             listAll(buff);
190             fprintf(stdout, "%s", buff);
191         }
192         else if(strcmp(cmd, "kill") == 0)
193         {
194             int clientIndex;
195             scanf("%d", &clientIndex);
196             if(clientIndex >= MAXCONN)
197             {
198                 fprintf(stderr, "Unkown client!\n");
199                 continue;
200             }
201             pthread_mutex_lock(&clientsMutex[clientIndex]);
202             if(clients[clientIndex].isConn)
203             {
204                 if(close(clients[clientIndex].clientfd) == -1)
205                     fprintf(stderr, "Close %d client eroor: %s(errno: %d)\n", clients[clientIndex].clientfd, strerror(errno), errno);
206             }
207             else
208             {
209                 fprintf(stderr, "Unknown client!\n");
210             }
211             pthread_mutex_unlock(&clientsMutex[clientIndex]);
212             pthread_cancel(threadID[clientIndex]);
213
214         }
215         else
216         {
217             fprintf(stderr, "Unknown command!\n");
218         }
219     }
220 }
221
222 int main()
223 {
224    int activeConn = 0;
225
226    //initialize the mutex
227    pthread_mutex_init(&activeConnMutex, NULL);
228    pthread_cond_init(&connDis, NULL);
229    int i=0;
230    for(;i<MAXCONN;++i)
231        pthread_mutex_init(&clientsMutex[i], NULL);
232
233    for(i=0;i<MAXCONN;++i)
234        clients[i].isConn = 0;
235
236    //create the server manager thread
237    pthread_create(&serverManagerID, NULL, (void *)(serverManager), NULL);
238
239
240    int listenfd;
241    struct sockaddr_in  servaddr;
242
243    //create a socket
244    if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
245    {
246        fprintf(stderr, "Create socket error: %s(errno: %d)\n", strerror(errno), errno);
247        exit(0);
248    }
249    else
250        fprintf(stdout, "Create a socket successfully\n");
251
252    fcntl(listenfd, F_SETFL, O_NONBLOCK);       //set the socket non-block
253
254    //set the server address
255    memset(&servaddr, 0, sizeof(servaddr));  //initialize the server address
256    servaddr.sin_family = AF_INET;           //AF_INET means using TCP protocol
257    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    //any in address(there may more than one network card in the server)
258    servaddr.sin_port = htons(PORT);            //set the port
259
260    //bind the server address with the socket
261    if(bind(listenfd, (struct sockaddr*)(&servaddr), sizeof(servaddr)) == -1)
262    {
263         fprintf(stderr, "Bind socket error: %s(errno: %d)\n", strerror(errno), errno);
264         exit(0);
265    }
266    else
267        fprintf(stdout, "Bind socket successfully\n");
268
269    //listen
270    if(listen(listenfd, BACKLOG) == -1)
271    {
272        fprintf(stderr, "Listen socket error: %s(errno: %d)\n", strerror(errno), errno);
273        exit(0);
274    }
275    else
276        fprintf(stdout, "Listen socket successfully\n");
277
278
279    while(1)
280    {
281        if(serverExit)
282        {
283            for(i=0;i<MAXCONN;++i)
284            {
285                if(clients[i].isConn)
286                {
287                    if(close(clients[i].clientfd) == -1)         //close the client
288                        fprintf(stderr, "Close %d client eroor: %s(errno: %d)\n", clients[i].clientfd, strerror(errno), errno);
289                    if(pthread_cancel(threadID[i]) != 0)         //cancel the corresponding client thread
290                         fprintf(stderr, "Cancel %d thread eroor: %s(errno: %d)\n", (int)(threadID[i]), strerror(errno), errno);
291                }
292            }
293            return 0;    //main exit;
294        }
295
296        pthread_mutex_lock(&activeConnMutex);
297        if(activeConn >= MAXCONN)
298             pthread_cond_wait(&connDis, &activeConnMutex);
299        pthread_mutex_unlock(&activeConnMutex);
300
301        //find an empty postion for a new connnetion
302        int i=0;
303        while(i<MAXCONN)
304        {
305            pthread_mutex_lock(&clientsMutex[i]);
306            if(!clients[i].isConn)
307            {
308                pthread_mutex_unlock(&clientsMutex[i]);
309                break;
310            }
311            pthread_mutex_unlock(&clientsMutex[i]);
312            ++i;
313        }
314
315        //accept
316        struct sockaddr_in addr;
317        int clientfd;
318        int sin_size = sizeof(struct sockaddr_in);
319        if((clientfd = accept(listenfd, (struct sockaddr*)(&addr), &sin_size)) == -1)
320        {
321            sleep(1);
322            //fprintf(stderr, "Accept socket error: %s(errno: %d)\n", strerror(errno), errno);
323            continue;
324            //exit(0);
325        }
326        else
327            fprintf(stdout, "Accept socket successfully\n");
328
329        pthread_mutex_lock(&clientsMutex[i]);
330        clients[i].clientfd = clientfd;
331        clients[i].addr = addr;
332        clients[i].isConn = 1;
333        clients[i].index = i;
334        pthread_mutex_unlock(&clientsMutex[i]);
335
336        //create a thread for a client
337        pthread_create(&threadID[i], NULL, (void *)clientManager, &clients[i]);
338
339    }    //end-while
340 }

客户端实现细节

客户端程序主要可以分成客户端主线程控制和服务端消息接受程序。

主线程

客户端的程序较服务端的程序则简单的多,主要是接受用户的指令按照指令执行相关的任务。这里主要实现了conn连接服务器,disconn断开服务器连接,list查询服务器上的所有连接,name查看服务器名字,time查看时间,send先其他的客户端发送消息这些命令。

客户端首先必须通过conn命令连接上对应的服务器,然后可以执行其他的指令。用户通过time,name查看时间和机器名,如果需要发送消息,可以通过list查看所有连接,然后向指定的连接发送消息,quit退出客户端。

服务器消息处理线程

由于主线程为一个阻塞的线程,因此这里创建了一个接受服务器端的消息的线程。当用户通过conn命令连接上服务器之后,主线程就会创建该接受线程,其不断的监听服务器发回的消息,然后将其输入的屏幕上。当用户通过disconn命令取消连接的时候,主线程则就会取消掉这个线程。下面是该线程相关的代码。

  1 #include <sys/types.h>
  2 #include <sys/socket.h>
  3 #include <stdio.h>
  4 #include <netinet/in.h>
  5 #include <arpa/inet.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <string.h>
  9 #include <stdlib.h>
 10 #include <pthread.h>
 11
 12 #define BUFFERSIZE 1024
 13 typedef unsigned char BYTE;
 14 pthread_t receiveID;
 15
 16 void tolowerString(char *s)
 17 {
 18     int i=0;
 19     while(i < strlen(s))
 20     {
 21         s[i] = tolower(s[i]);
 22         ++i;
 23     }
 24 }
 25
 26 void receive(void *argv)
 27 {
 28     int sockclient = *(int*)(argv);
 29     BYTE recvbuff[BUFFERSIZE];
 30     while(recv(sockclient, recvbuff, sizeof(recvbuff), 0)!=-1) //receive
 31     {
 32         fputs(recvbuff, stdout);
 33         fputs("\n", stdout);
 34     }
 35     fprintf(stderr, "Receive eroor: %s(errno: %d)\n", strerror(errno), errno);
 36 }
 37
 38 int main()
 39 {
 40     ///define sockfd
 41     int sockclient = socket(AF_INET,SOCK_STREAM, 0);
 42
 43     ///definet sockaddr_in
 44     struct sockaddr_in servaddr;
 45     memset(&servaddr, 0, sizeof(servaddr));
 46
 47     int isConn = 0;
 48
 49     BYTE buff[BUFFERSIZE];
 50
 51
 52     while (fgets(buff, sizeof(buff), stdin) != NULL)
 53     {
 54         tolowerString(buff);
 55         char cmd[100], ip[100];
 56         int port;
 57         if(sscanf(buff, "%s", cmd) == -1)    //command error
 58         {
 59             fprintf(stderr, "Input eroor: %s(errno: %d) And please input again\n", strerror(errno), errno);
 60             continue;
 61         }
 62         if(strcmp(cmd, "conn") == 0)        //connecton command
 63         {
 64             char ip[100];
 65             int port, ipLen=0;
 66             if(sscanf(buff+strlen(cmd)+1, "%s", ip) == -1)    //command error
 67             {
 68                 fprintf(stderr, "Input eroor: %s(errno: %d) And please input again\n", strerror(errno), errno);
 69                 continue;
 70             }
 71             if((sscanf(buff+strlen(cmd)+strlen(ip)+2, "%d", &port)) == -1)    //command error
 72             {
 73                 fprintf(stderr, "Input eroor: %s(errno: %d) And please input again\n", strerror(errno), errno);
 74                 continue;
 75             }
 76            // fprintf(stdout, "%s %d\n",ip, port);
 77             servaddr.sin_family = AF_INET;
 78             servaddr.sin_port = htons(port);  ///server port
 79             servaddr.sin_addr.s_addr = inet_addr(ip);  //server ip
 80             if (connect(sockclient, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
 81             {
 82                 fprintf(stderr, "Connect eroor: %s(errno: %d)\n", strerror(errno), errno);
 83                 continue;
 84             }
 85             fprintf(stdout, "Connect successfully\n");
 86             isConn = 1;
 87             pthread_create(&receiveID, NULL, (void *)(receive), (void *)(&sockclient));
 88         }
 89         else if(strcmp(cmd, "disconn") == 0)
 90         {
 91             if(isConn == 0)
 92             {
 93                 fprintf(stdout, "There is not a connection!\n");
 94                 continue;
 95             }
 96             else
 97             {
 98                 pthread_cancel(receiveID);
 99                 close(sockclient);
100             }
101             isConn = 0;
102         }
103         else if(strcmp(cmd, "quit") == 0)
104         {
105             if(isConn)
106             {
107                 pthread_cancel(receiveID);
108                 close(sockclient);
109             }
110             return 0;
111         }
112         else
113         {
114             if(send(sockclient, buff, strlen(buff)+1, 0) == -1) //send
115             {
116                 fprintf(stderr, "Send eroor: %s(errno: %d)\n", strerror(errno), errno);
117                 continue;
118             }
119
120             if(isConn == 0)
121             {
122                 fprintf(stdout, "Please use conn <ip> <port> command to build a connnection!\n");
123                 continue;
124             }
125             memset(buff, 0, sizeof(buff));
126         }
127     }
128
129     close(sockclient);
130     return 0;
131 }

程序测试结果

实验测试采用了3个客户端同时连接一个服务端进行测试。同时运行这四个程序,首先3个客户端通过conn命令连接上客户端,我们发现3个客户端都同时连接上,说明conn命令正常工作,socket建立正确。然后在客户端1中我们对一些命令进行测试,输入name发现返回了机器的名字,输入time返回了时间,输入list,方向其显示了3个客户端的连接信息。这说明了name,time和list都正常工作。然后在客户端中通过send命令先客户端2发送一条消息,发现客户端2收到了消息,然后客户端2回复了一条消息,客户端1也收到了消息。先客户端3发送消息,其也正常的收到,其发送消息给客户端2,客户端2也能正常收到。着说明了程序中send命令运行正常,能够进行消息的收发。最后客户端1,2,3都通过quit命令退出了客户端,并且服务器端收到了该退出的消息,并且关闭了该连接和线程,最后服务器端退出了。

服务器

客户端1

客户端2

客户端3

时间: 2024-10-01 04:07:47

Linux下的基于Pthread的多线程Socket编程的相关文章

linux下mysql基于mycat做主从复制和读写分离之基础篇

Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , mycat1.6-RELEASE jdk1.7及其以上版本2.实现步骤一(mycat实现读写分离) 1.首先在两台服务器安装mysql 1.下载mysql的repo源 $ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rp

Linux下c基于openssl生成MD5的函数

Linux下openssl提供了一系列哈希及加密的函数,如果调用openssl提供的MD5函数生成任意字符串的MD5呢?下面提供了一段代码实现Linux下c字符串生成md5的函数. 具体代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include "stdio.h" #include <string.h> #include <stdlib.h&

网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服务器进程B1同时为客户进程A1.A2和B2提供服务. Socket概述 ①   所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过“套接字”向网络发出请求或者应答网络请求. ②   Socket是连接运行在网络上的两个程序间的双向通信的端点. ③  

基于TCP/UDP的socket编程

基于TCP(面向连接)的socket编程服务器端顺序: 1. 创建套接字(socket) 2. 将套接字绑定到一个本地地址和端口上(bind) 3. 将套接字设为监听模式,准备接收客户请求(listen) 4. 等待客户请求的到来:当请求带来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept) 5. 用返回的套接字和客户端进行通信(send/recv) 6. 返回,等待另一个客户请求 7. 关闭套接字(closesocket)客户端程序: 1. 创建套接字(socket) 2.

基于UDP协议之——socket编程

一. socket API 前面一篇<基于TCP协议之--socket编程>http://2627lounuo.blog.51cto.com/10696599/1775559已经花了大量的篇幅讲述了socket和使用基本的socket API所需要注意的问题,这里就不再赘述了.下面主要谈论的是UDP和TCP在socket编程中的不同之处: 1. 创建sock 和TCP面向连接的可靠的字节流传输服务不同的是,UDP是无连接的不可靠的数据报传输服务:虽然有所不同,但同样在进程间通信的时候需要提供出

Linux下常用的C/C++开源Socket库

1.      Linux Socket Programming In C++ : http://tldp.org/LDP/LG/issue74/tougher.html 2.      ACE: http://www.cs.wustl.edu/~schmidt/ACE.html ACE采用ACE_OS适配层屏蔽各种不同的.复杂繁琐的操作系统API. ACE是一个大型的中间件产品,代码20万行左右,过于宏大,一堆的设计模式,架构了一层又一层.它庞大.复杂,适合大型项目.开源.免费,不依赖第三方库

Linux下,基于EETI触屏控制器的触屏失灵解决方法

Linux(kernel 3.2.x)下,基于EETI触屏控制器.USB触控线的触屏应用,发现将USB触控线拔掉再插上后,触屏失灵,此时触屏驱动 eGTouhD的CPU急剧飙升,占用率在90%以上. 查看触屏设备,发现USB触控线拔掉后,/dev/hidraw仍然存在,没有及时remove,此时再插上USB触控线,会在/dev下出现hidraw0的设备.因此判断故障点出在这里:USB触控线拔掉后,触控设备实际上已不存在,但是/dev/hidraw的存在使eGTouhD认为触控设备还存在,一直在读

使用libevent进行多线程socket编程demo

最近要对一个用libevent写的C/C++项目进行修改,要改成多线程的,故做了一些学习和研究. libevent是一个用C语言写的开源的一个库.它对socket编程里的epoll/select等功能进行了封装,并且使用了一些设计模式(比如反应堆模式),用事件机制来简化了socket编程.libevent的好处网上有很多,但是初学者往往都看不懂.我打个比方吧,1)假设有N个客户端同时往服务端通过socket写数据,用了libevent之后,你的server程序里就不用再使用epoll或是sele

Java网络编程基础(二)-- 基于TCP/IP的Socket编程

本节讲点: 客户端套接字:Socket:Socket的创建和使用方法,以及Socket选项和异常. 服务端套接字:ServerSocket:SeverSocket的创建和使用方法,以及ServerSocket选项 简单的Client/Server对话程序 支持多客户端的Client/Server服务响应程序 在学习JDK的网络编程之前先要了解一下网络基础知识和网络协议. TCP(传输控制协议)一种基于连接的通信协议.可靠传输 UDP(用户数据包协议)不稳定连接的通信协议 TCP和UDP的端口如下