很好很好的select模型的客户端与服务器例子



服务端程序:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片

1. #include <stdio.h>  

2. #include <winsock2.h>     

3. #pragma comment(lib, "ws2_32.lib")  

4.   

5. int totalSockets = 0; // socket的总数  

6. SOCKET socketArray[100]; // socket组成的数组, 假设最多有100socket  

7.   

8. // 日志打印  

9. void log(const char *pStr)  

10.{  

11.    FILE *fp = fopen("log.txt""a");  

12.    fprintf(fp, "log:%s\n", pStr);  

13.    fclose(fp);  

14.}  

15.  

16.// 创建socket  

17.void addToSocketArr(SOCKET s)     

18.{  

19.    socketArray[totalSockets] = s;         

20.    totalSockets++;   

21.}  

22.  

23.// 启动服务器  

24.int main()  

25.{  

26.    log("into main");  

27.  

28.    // 网络初始化  

29.    WSADATA   wsaData;  

30.    WSAStartup(MAKEWORD(1, 1), &wsaData);  

31.  

32.    // 创建socket  

33.    SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);  

34.    addToSocketArr(listenSocket);      

35.     

36.    // 服务地信息  

37.    SOCKADDR_IN   srvAddr;  

38.    srvAddr.sin_family = AF_INET;     

39.    srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);     

40.    srvAddr.sin_port = htons(8888);    

41.      

42.    // 绑定  

43.    bind(listenSocket, (SOCKADDR*)&srvAddr, sizeof(srvAddr));   

44.    

45.    // 监听  

46.    listen(listenSocket, 5);   

47.    

48.    // 设置socket为非阻塞模式  

49.    unsigned long nonBlock = 1;     

50.    ioctlsocket(listenSocket, FIONBIO, &nonBlock);   

51.   

52.    while(1)     

53.    {  

54.        // 读集要记得清零初始化  

55.        FD_SET   readSet;  

56.        FD_ZERO(&readSet);     

57.  

58.        // 将每个socket都塞入读集, 便于让内核来监测这些socket  

59.        int i = 0;  

60.        for(i = 0; i < totalSockets; i++)     

61.        {              

62.            FD_SET(socketArray[i], &readSet);      

63.        }  

64.  

65.        // 应用程序通知内核来监测读集中的socket, 最后的NULL表示超时时间无限长  

66.        int total = select(0, &readSet, NULL, NULL, NULL);    

67.        

68.        // 我们不考虑select失败, 那么程序到这里, 说明读集中必有socket处于"就绪状态"  

69.        for(i = 0; i < totalSockets; i++)     

70.        {  

71.            char szTmp[20] = {0};  

72.            sprintf(szTmp, "%d", i);  

73.            log(szTmp);  

74.  

75.            if(socketArray[i] == listenSocket)  // 对监听的socket进行判断  

76.            {  

77.                log("socketArray[i] == listenSocket");  

78.  

79.                if(FD_ISSET(listenSocket, &readSet)) // 如果该socket在可读集中, 则表明有客户端来连接  

80.                {  

81.  

82.                    log("listenSocket, socketArray[i] == listenSocket");  

83.  

84.                    // 接收来自于客户端的connect请求  

85.                    SOCKADDR_IN addrClient;    

86.                    int len = sizeof(SOCKADDR);  

87.                    SOCKET acceptSocket = 0;  

88.                    acceptSocket = accept(listenSocket,(SOCKADDR*)&addrClient, &len);  

89.   

90.                    // 设置为非阻塞模式  

91.                    nonBlock = 1;     

92.                    ioctlsocket(acceptSocket, FIONBIO, &nonBlock);  

93.  

94.                    // 添加到socket数组中  

95.                    addToSocketArr(acceptSocket);  

96.                }  

97.  

98.                continue;  

99.            }  

100.    

101.    

102.              // 注意:上面的listenSocket是不负责通信的, 下面的一些socket都是负责通信的socket  

103.    

104.    

105.              // 如果通信socket处于读就绪状态  

106.              if (FD_ISSET(socketArray[i], &readSet))     

107.              {  

108.                  log("to receive");  

109.    

110.                  char szRecvBuf[1024] = {0};  

111.                  recv(socketArray[i], szRecvBuf, sizeof(szRecvBuf) - 1, 0);     

112.                  printf("socketArray[i] is %d, %s\n", socketArray[i], szRecvBuf);  

113.              }  

114.          }             

115.      }  

116.    

117.      // 省略了关闭socket等后续操作  

118.    

119.      return 0;  

120.  }  

#include<stdio.h>

#include<winsock2.h>  

#pragmacomment(lib, "ws2_32.lib")

 

inttotalSockets = 0; // socket的总数

SOCKETsocketArray[100]; // socket组成的数组,假设最多有100socket

 

// 日志打印

voidlog(const char *pStr)

{

FILE *fp = fopen("log.txt","a");

fprintf(fp, "log:%s\n", pStr);

fclose(fp);

}

 

// 创建socket

voidaddToSocketArr(SOCKET s)  

{

    socketArray[totalSockets] = s;      

    totalSockets++;

}

 

// 启动服务器

intmain()

{

log("into main");

 

// 网络初始化

WSADATA  wsaData;

    WSAStartup(MAKEWORD(1, 1), &wsaData);

 

// 创建socket

    SOCKET listenSocket = socket(AF_INET,SOCK_STREAM, 0);

    addToSocketArr(listenSocket);   

  

// 服务地信息

SOCKADDR_IN  srvAddr;

    srvAddr.sin_family = AF_INET;  

    srvAddr.sin_addr.s_addr =htonl(INADDR_ANY);  

    srvAddr.sin_port = htons(8888); 

// 绑定

    bind(listenSocket, (SOCKADDR*)&srvAddr,sizeof(srvAddr));

 

// 监听

    listen(listenSocket, 5);

 

// 设置socket为非阻塞模式

    unsigned long nonBlock = 1;  

    ioctlsocket(listenSocket, FIONBIO,&nonBlock);

 

while(1)  

    {

// 读集, 要记得清零初始化

FD_SET  readSet;

        FD_ZERO(&readSet);  

 

// 将每个socket都塞入读集, 便于让内核来监测这些socket

int i = 0;

        for(i = 0; i < totalSockets;i++)  

{           

  FD_SET(socketArray[i], &readSet);   

}

 

// 应用程序通知内核来监测读集中的socket, 最后的NULL表示超时时间无限长

int total = select(0, &readSet, NULL, NULL,NULL); 

     

// 我们不考虑select失败, 那么程序到这里, 说明读集中必有socket处于"就绪状态"

        for(i = 0; i < totalSockets;i++)  

{

  char szTmp[20] = {0};

  sprintf(szTmp, "%d", i);

  log(szTmp);

 

  if(socketArray[i] == listenSocket) // 对监听的socket进行判断

  {

  log("socketArray[i] ==listenSocket");

 

  if(FD_ISSET(listenSocket, &readSet)) // 如果该socket在可读集中, 则表明有客户端来连接

  {

 

   log("listenSocket, socketArray[i] ==listenSocket");

 

   // 接收来自于客户端的connect请求

   SOCKADDR_IN addrClient; 

   int len = sizeof(SOCKADDR);

   SOCKET acceptSocket = 0;

   acceptSocket =accept(listenSocket,(SOCKADDR*)&addrClient, &len);

 

   // 设置为非阻塞模式

   nonBlock = 1;  

   ioctlsocket(acceptSocket, FIONBIO,&nonBlock);

 

   // 添加到socket数组中

   addToSocketArr(acceptSocket);

  }

 

  continue;

  }

 

 

  // 注意:上面的listenSocket是不负责通信的, 下面的一些socket都是负责通信的socket

 

 

  // 如果通信socket处于读就绪状态

  if (FD_ISSET(socketArray[i],&readSet))  

            {

  log("to receive");

 

  char szRecvBuf[1024] = {0};

  recv(socketArray[i], szRecvBuf,sizeof(szRecvBuf) - 1, 0);  

  printf("socketArray[i] is %d, %s\n",socketArray[i], szRecvBuf);

  }

}  

    }

 

// 省略了关闭socket等后续操作

 

return 0;

}

      启动服务端。

      

      再看客户端程序:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片

1. #include <winsock2.h>  

2. #include <stdio.h>  

3. #pragma comment(lib, "ws2_32.lib")  

4.   

5. int main()  

6. {  

7.     WORD wVersionRequested;  

8.     WSADATA wsaData;  

9.     wVersionRequested = MAKEWORD(1, 1);  

10.      

11.    WSAStartup( wVersionRequested, &wsaData );  

12.  

13.    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);  

14.  

15.    SOCKADDR_IN addrSrv;  

16.    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  

17.    addrSrv.sin_family = AF_INET;  

18.    addrSrv.sin_port = htons(8888);  

19.      

20.    connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));  

21.      

22.  

23.    while(1)  

24.    {  

25.        char szSendBuf[100] = {0};  

26.        scanf("%s", szSendBuf);  

27.        send(sockClient, szSendBuf, strlen(szSendBuf) + 1, 0);  

28.    }  

29.  

30.    closesocket(sockClient);  

31.    WSACleanup();  

32.  

33.    return 0;  

34.}  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值