zoukankan      html  css  js  c++  java
  • I/O复用(select)——回声服务器端/客户端

     一、select

      使用select函数可以将多个文件描述符集中到一起统一监视,监视事件如下:

    • 是否存在待读取数据。
    • 是否可传输无阻塞传输数据。
    • 是否发生异常。

      将关心上述3种事件的文件描述发分别注册到对应参数(readfds,writefds,exceptfds)中去。

      int select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

    1、linux

    服务器端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <arpa/inet.h>
     6 #include <sys/socket.h>
     7 
     8 #define BUF_SIZE 1024
     9 void error_handling(char * messages);
    10 
    11 int main(int argc, char *argv[])
    12 {
    13     if(argc != 2)
    14     {
    15         printf("Usage : %s <port>
    ", argv[0]);
    16         exit(1);
    17     }
    18     int serverSock, clientSock;
    19     struct sockaddr_in serverAddr, clientAddr;
    20     socklen_t clientAddrSize;
    21 
    22     struct timeval timeout;
    23     fd_set reads, cpy_reads;
    24     int fd_max, fd_num;
    25 
    26     char message[BUF_SIZE];
    27     int strLen;
    28 
    29     serverSock =socket(PF_INET, SOCK_STREAM, 0);
    30     if(serverSock == -1)
    31         error_handling("socket() error");
    32 
    33     memset(&serverAddr, 0, sizeof(serverAddr));
    34     serverAddr.sin_family = AF_INET;
    35     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    36     serverAddr.sin_port = htons(atoi(argv[1]));
    37 
    38     if(bind(serverSock, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) == -1)
    39         error_handling("bind() error");
    40     if(listen(serverSock, 5) == -1)
    41         error_handling("listen() error");
    42 
    43     FD_ZERO(&reads);
    44     FD_SET(serverSock, &reads);
    45     fd_max = serverSock;
    46 
    47     puts("Server start...");
    48     while(1){
    49         cpy_reads = reads;
    50         timeout.tv_sec = 5;
    51         timeout.tv_usec = 5000;
    52 
    53         if((fd_num = select(fd_max+1, &cpy_reads, 0, 0, &timeout)) == -1){
    54             error_handling("select() error");
    55             break;
    56         }
    57         if(fd_num == 0) continue;
    58         for(int i = 0; i <= fd_max; i++){
    59             if(FD_ISSET(i, &cpy_reads)){
    60                 if(i == serverSock){ // connection request
    61                     clientAddrSize = sizeof(clientAddr);
    62                     clientSock = accept(serverSock, (struct sockaddr*)&clientAddr, &clientAddrSize);
    63                     FD_SET(clientSock, &reads);
    64                     if(fd_max < clientSock)
    65                         fd_max = clientSock;
    66                     printf("connected client: %d
    ", clientSock);
    67                 }
    68                 else{ // read message
    69                     strLen = read(i, message, BUF_SIZE);
    70                     if(strLen == 0){
    71                         FD_CLR(i, &reads);
    72                         close(i);
    73                         printf("close client: %d
    ", i);
    74                     }
    75                     else{
    76                         write(i, message, strLen);
    77                         printf("echo: %d
    ",i);
    78                     }
    79                 }
    80             }
    81         }
    82     }
    83     close(serverSock);
    84     puts("Server close...");
    85     return 0;
    86 }
    87 
    88 void error_handling(char * messages)
    89 {
    90     puts(messages);
    91     exit(1);
    92 }
    View Code

    客户端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <arpa/inet.h>
     6 #include <sys/socket.h>
     7 
     8 #define BUF_SIZE 1024
     9 void error_handling(char * messages);
    10 
    11 int main(int argc, char *argv[])
    12 {
    13     if(argc != 3)
    14     {
    15         printf("Usage : %s <IP> <port>
    ", argv[0]);
    16         exit(1);
    17     }
    18     int sock;
    19     struct sockaddr_in serv_addr;
    20     char message[BUF_SIZE];
    21     int strLen;
    22 
    23     sock = socket(PF_INET, SOCK_STREAM, 0);
    24     if(sock == -1)
    25         error_handling("socket() error");
    26 
    27     memset(&serv_addr, 0, sizeof(serv_addr));
    28     serv_addr.sin_family = AF_INET;
    29     serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    30     serv_addr.sin_port = htons(atoi(argv[2]));
    31 
    32     if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
    33         error_handling("connect() error");
    34     else
    35         puts("Connected...");
    36     while(1){
    37         puts("Input message(Q to quit):");
    38         fgets(message, BUF_SIZE, stdin);
    39         if(!strcmp(message, "q
    ") || !strcmp(message, "Q
    "))
    40             break;
    41 
    42         strLen=strlen(message);
    43         write(sock, message, strlen(message));
    44         int recvLen = 0;
    45         while(recvLen < strLen){
    46             int recvCnt = read(sock, &message[recvLen], BUF_SIZE-1);
    47             if(recvCnt == -1)
    48                 error_handling("read() error");
    49             recvLen+=recvCnt;
    50         }
    51         message[recvLen]=0;
    52         printf("Message from server: %s
    ", message);
    53     }
    54     close(sock);
    55     return 0;
    56 }
    57 
    58 void error_handling(char * messages)
    59 {
    60     puts(messages);
    61     exit(1);
    62 }
    View Code

    2、windows

    服务器端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <WinSock2.h>
     4 
     5 #define BUF_SIZE 1024
     6 void ErrorHandling(char *message);
     7 
     8 int main(int argc, char *argv[])
     9 {
    10     if (argc != 2) {
    11         printf("Usage : %s <port>
    ", argv[0]);
    12         exit(1);
    13     }
    14 
    15     WSADATA wsa_data;
    16     SOCKET server_sock, client_sock;
    17     SOCKADDR_IN server_addr, client_addr;
    18     TIMEVAL time_out;
    19     fd_set reads, temp_reads;
    20 
    21     int addr_size;
    22     int str_len, fd_num;
    23     char buf[BUF_SIZE];
    24 
    25     if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
    26         ErrorHandling("WSAStartup() error.");
    27 
    28     server_sock = socket(PF_INET, SOCK_STREAM, 0);
    29     if (server_sock == INVALID_SOCKET)
    30         ErrorHandling("socket() error.");
    31 
    32     memset(&server_addr, 0, sizeof(server_addr));
    33     server_addr.sin_family = AF_INET;
    34     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    35     server_addr.sin_port = htons(atoi(argv[1]));
    36 
    37     if (bind(server_sock, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
    38         ErrorHandling("bind() error.");
    39     if (listen(server_sock, 5) == SOCKET_ERROR)
    40         ErrorHandling("listen() error.");
    41     printf("Server start...
    ");
    42     FD_ZERO(&reads);
    43     FD_SET(server_sock, &reads);
    44     while (true)
    45     {
    46         temp_reads = reads;
    47         time_out.tv_sec = 5;
    48         time_out.tv_usec = 5000;
    49         if ((fd_num = select(0, &temp_reads, 0, 0, &time_out)) == SOCKET_ERROR)
    50             break;
    51         if (fd_num == 0)
    52             continue;
    53         for (int i = 0; i < reads.fd_count; ++i)
    54         {
    55             if (FD_ISSET(reads.fd_array[i], &temp_reads))
    56             {
    57                 if (reads.fd_array[i] == server_sock) // connection request
    58                 {
    59                     addr_size = sizeof(client_addr);
    60                     client_sock = accept(server_sock, (SOCKADDR*)&client_addr, &addr_size);
    61                     if (client_sock == INVALID_SOCKET)
    62                         ErrorHandling("accept() error.");
    63                     FD_SET(client_sock, &reads);
    64                     printf("connected client: %d
    ", client_sock);
    65                 }
    66                 else // read message
    67                 {
    68                     str_len = recv(reads.fd_array[i], buf, BUF_SIZE - 1, 0);
    69                     if (str_len == 0)
    70                     {
    71                         FD_CLR(reads.fd_array[i], &reads);
    72                         closesocket(temp_reads.fd_array[i]);
    73                         printf("close client: %d
    ", temp_reads.fd_array[i]);
    74                     }
    75                     else
    76                     {
    77                         send(reads.fd_array[i], buf, str_len, 0); // echo
    78                     }
    79                 }
    80             }
    81         }
    82     }
    83     closesocket(server_sock);
    84     WSACleanup();
    85     printf("Server end...
    ");
    86     return 0;
    87 }
    88 
    89 void ErrorHandling(char *message) {
    90     fputs(message, stderr);
    91     fputc('
    ', stderr);
    92 }
    View Code

    客户端:

     1 #pragma warning(disable:4996)
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <winsock2.h>
     6 
     7 #define BUF_SIZE 1024
     8 void ErrorHandling(char *message);
     9 
    10 int main(int argc, char* argv[]) {
    11     if (argc != 3) {
    12         printf("Usage : %s <IP> <port>
    ", argv[0]);
    13         exit(1);
    14     }
    15 
    16     WSADATA wsaData;
    17     SOCKET sock;
    18     SOCKADDR_IN serverAddr;
    19     char message[BUF_SIZE];
    20     int sLen, recvLen;
    21 
    22     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    23         ErrorHandling("WSAStartup() error");
    24 
    25     sock = socket(PF_INET, SOCK_STREAM, 0);
    26     if (sock == INVALID_SOCKET)
    27         ErrorHandling("socket() error");
    28 
    29     memset(&serverAddr, 0, sizeof(serverAddr));
    30     serverAddr.sin_family = AF_INET;
    31     serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
    32     serverAddr.sin_port = htons(atoi(argv[2]));
    33 
    34     if (connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
    35         ErrorHandling("connect() error");
    36     else
    37         printf("Connected.......
    ");
    38     while (1)
    39     {
    40         fputs("Input message(Q to quit):", stdout);
    41         fgets(message, BUF_SIZE, stdin);
    42         if (!strcmp(message, "q
    ") || !strcmp(message, "Q
    "))
    43             break;
    44         sLen = send(sock, message, strlen(message), 0);
    45         recvLen = 0;
    46         while (recvLen < sLen) {
    47             int cnt = recv(sock, message, BUF_SIZE - 1, 0);
    48             if (cnt == -1)
    49                 ErrorHandling("ercv() error");
    50             recvLen += cnt;
    51         }
    52         message[recvLen] = 0;
    53         printf("Message from server: %s
    ", message);
    54     }
    55     closesocket(sock);
    56     WSACleanup();
    57     return 0;
    58 }
    59 
    60 void ErrorHandling(char *message) {
    61     fputs(message, stderr);
    62     fputc('
    ', stderr);
    63 }
    View Code
  • 相关阅读:
    鼠标跟随效果 vue或者js通用
    element 多个文件上传多次http请求解决方法
    快速判断数组中值是否重复
    vue-resource+element upload上传(遇到formData总是变为object格式)
    element UI 下拉菜单滚动监听(vue指令)
    echarts环形图自动定位radius
    echarts地图散点高亮弹框制作
    js实现table表格相同内容按需合并
    element ui表格相同内容自动合并
    hadoop yarn
  • 原文地址:https://www.cnblogs.com/ACGame/p/9914732.html
Copyright © 2011-2022 走看看