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
  • 相关阅读:
    jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解
    jQuery 源码解析(二十三) DOM操作模块 替换元素 详解
    jQuery 源码解析(二十二) DOM操作模块 复制元素 详解
    jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
    jQuery 源码分析(二十) DOM操作模块 插入元素 详解
    jQuery 源码分析(十九) DOM遍历模块详解
    python 简单工厂模式
    python 爬虫-协程 采集博客园
    vue 自定义image组件
    微信小程序 image组件坑
  • 原文地址:https://www.cnblogs.com/ACGame/p/9914732.html
Copyright © 2011-2022 走看看