首页 > 代码库 > 非阻塞模式(ioctlsocket)

非阻塞模式(ioctlsocket)

  1     //Server.cpp    2     #include <stdio.h>    3     #include <winsock2.h>             //winsock.h (2种套接字版本)    4     #pragma comment(lib,"ws2_32.lib") //wsock32.lib    5        6     #define MAXSIZE 100 //    7        8     int main()    9     {   10         //   11         int retVal;   12       13         char buf[MAXSIZE];   14       15         //初始化套接字库   16         WORD wVersionRequest;   17         WSADATA wsadata;   18       19         wVersionRequest=MAKEWORD(2,2);   20       21         retVal=WSAStartup(wVersionRequest,&wsadata);   22         if(retVal == SOCKET_ERROR)   23         {   24             printf("WSAStartup failed!");   25       26             return -1;   27         }   28       29         //创建套接字   30         SOCKET sServer;   31         sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);   32         if(sServer == INVALID_SOCKET)   33         {   34             printf("socket failed!");   35       36             WSACleanup();   37             return -1; //每次检测到失败后,即需要返回   38         }   39       40         //设置为非阻塞模式   41         int imode=1;   42         retVal=ioctlsocket(sServer,FIONBIO,(u_long *)&imode);   43         if(retVal == SOCKET_ERROR)   44         {   45             printf("ioctlsocket failed!");   46       47             closesocket(sServer);   48             WSACleanup();   49             return -1;   50         }   51       52         //绑定套接字并将其设置为监听状态   53         SOCKADDR_IN addrServ;   54         addrServ.sin_family=AF_INET;   55         addrServ.sin_port  =htons(5000);   56         addrServ.sin_addr.S_un.S_addr=inet_addr("192.168.0.102");   57       58         retVal=bind(sServer,(SOCKADDR *)&addrServ,sizeof(addrServ)); //绑定套接字到某一个具体的服务器   59         if(retVal == SOCKET_ERROR)   60         {   61             printf("bind failed!");   62       63             closesocket(sServer);   64             WSACleanup();   65             return -1;   66         }   67       68         retVal=listen(sServer,1); //第二个参数,表示最大连接数目   69         if(retVal == SOCKET_ERROR)   70         {   71             printf("listen failed!");   72       73             closesocket(sServer);   74             WSACleanup();   75             return -1;   76         }   77       78       79         //接受连接   80         sockaddr_in addrClient; //定义一个临时地址,用于接受连接(注意:某个客户端由Client.cpp确定)   81         int len=sizeof(sockaddr_in);   82       83         SOCKET sClient;   84         int errcode;   85       86         while(true)   87         {   88             sClient=accept(sServer,(sockaddr *)&addrClient,&len);   89             if(sClient == INVALID_SOCKET)   90             {   91                 errcode=WSAGetLastError();   92                 if(errcode == WSAEWOULDBLOCK)  //表示没有客户端发起连接,继续循环   93                 {   94                     Sleep(100);   95                     continue;   96                 }   97                 else  98                 {   99                     printf("accept failed!");  100      101                     closesocket(sServer); //连接失败,关闭服务器套接字并释放套接字库  102                     WSACleanup(); //  103                     return -1;  104                 }  105             }  106      107             break; //  108         }  109      110         //接收数据  111         while(true)  112         {  113             retVal=recv(sClient,buf,strlen(buf),0);  114             if(retVal == SOCKET_ERROR)  115             {  116                 errcode=WSAGetLastError(); //这个变量errcode没有重复定义吗?  117                 if(errcode == WSAEWOULDBLOCK)  //  118                 {  119                     Sleep(100);  120                     continue;  121                 }  122                 else 123                 {  124                     if(errcode==WSAETIMEDOUT || errcode==WSAENETDOWN)  125                     {  126                         closesocket(sClient);  127                         closesocket(sServer);  128                         WSACleanup();  129                         return -1;  130                     }  131                 }  132             }  133      134             if(buf == "quit") //如果接收数据为"quit",则发送回显"quit"  135             {  136                 retVal=send(sClient,buf,strlen(buf),0);  137                 break;  138             }  139             else 140             {  141                 //发送数据  142                 while(true)  143                 {  144                     retVal=send(sClient,buf,strlen(buf),0); //a.回显接收数据;b.第四个参数:0?  145                     if(retVal == SOCKET_ERROR)  //错误处理  146                     {  147                         errcode=WSAGetLastError();  148                         if(errcode == WSAEWOULDBLOCK)  //  149                         {  150                             Sleep(100);  151                             continue;  152                         }  153                         else 154                         {  155                             closesocket(sClient);  156                             closesocket(sServer);  157                             WSACleanup();  158                             return -1;  159      160                         }  161                     }  162      163                     break; //如果发送数据成功,则退出循环  164                 }  165      166             }  167         }  168      169     } 
  1     //Client.cpp    2     #include <stdio.h>    3     #include <WinSock2.h> //winsock.h    4     #pragma comment(lib,"ws2_32.lib"); //wsock32.lib    5        6     #include <iostream>    7     using namespace std;    8        9     #include <string.h> //strcpy函数   10       11     #define MAXSIZE 100 //   12       13     int main()   14     {   15         //   16         int retVal;   17       18         char buf[MAXSIZE];   19       20         //初始化套接字库   21         WORD wVersionRequest;   22         WSADATA wsadata;   23       24         wVersionRequest=MAKEWORD(2,2);   25       26         retVal=WSAStartup(wVersionRequest,&wsadata);   27         if(retVal == SOCKET_ERROR)   28         {   29             printf("WSAStartup failed!");   30       31             return -1;   32         }   33       34         //创建套接字   35         SOCKET sClient;   36         sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);   37         if(sClient == INVALID_SOCKET)   38         {   39             printf("socket failed!");   40       41             WSACleanup();   42             return -1; //每次检测到失败后,即需要返回   43         }   44       45         //设置为非阻塞模式   46         int imode=1;   47         retVal=ioctlsocket(sClient,FIONBIO,(u_long *)&imode);   48         if(retVal == SOCKET_ERROR)   49         {   50             printf("ioctlsocket failed!");   51       52             closesocket(sClient);   53             WSACleanup();   54             return -1;   55         }   56       57       58         //发起连接   59         sockaddr_in addrServ;   60         addrServ.sin_family=AF_INET; //表示使用的是,TCP/IP地址家族   61         addrServ.sin_port  =htons(5000); //为什么要使用htons宏?   62         addrServ.sin_addr.S_un.S_addr=inet_addr("192.168.0.102");   63       64         int len=sizeof(sockaddr_in); //sizeof只是一个运算符,不是函数   65       66         while(true)   67         {   68             retVal=connect(sClient,(sockaddr *)&addrServ,len); //连接到某一个具体的服务器   69             if(retVal == INVALID_SOCKET)   70             {   71                 int errcode=WSAGetLastError();   72                 if(errcode==WSAEWOULDBLOCK || errcode==WSAEINVAL)  //表示服务器端未准备好,继续循环   73                 {   74                     Sleep(100);   75                     continue;   76                 }   77                 else  78                 {   79                     if(errcode == WSAEISCONN) //连接成功,则退出   80                     {   81                         break;    82                     }   83                     else                      //否则连接失败,关闭客户端套接字并释放套接字库   84                     {   85                         printf("connect failed!");   86       87                         closesocket(sClient);    88                         WSACleanup(); //   89                         return -1;   90                     }   91                  }   92             }   93       94         }   95       96         //发送数据   97         while(true)   98         {   99             //  100             //scanf(buf);  101             //cin>>buf;  102      103             strcpy(buf,"Hello TCP!");  104      105             retVal=send(sClient,buf,strlen(buf),0); //a.回显接收数据;b.第四个参数:0?  106             if(retVal == SOCKET_ERROR)  //错误处理  107             {  108                 int errcode=WSAGetLastError();  109                 if(errcode == WSAEWOULDBLOCK)  //  110                 {  111                     Sleep(100);  112                     continue;  113                 }  114                 else 115                 {  116                     printf("send failed!");  117      118                     closesocket(sClient);  119                     //closesocket(sServer);  120                     WSACleanup();  121                     return -1;  122      123                 }  124             }  125      126             break; //如果发送数据成功,则退出循环  127         }  128      129         //接收数据  130         while(true)  131         {  132             retVal=recv(sClient,buf,strlen(buf),0);  133             if(retVal == SOCKET_ERROR)  134             {  135                 int errcode=WSAGetLastError(); //这个变量errcode没有重复定义吗?  136                 if(errcode == WSAEWOULDBLOCK)  //  137                 {  138                     Sleep(100);  139                     continue;  140                 }  141                 else 142                 {  143                     if(errcode==WSAETIMEDOUT || errcode==WSAENETDOWN)  144                     {  145                         printf("recv failed!");  146      147                         closesocket(sClient);  148                         //closesocket(sServer);  149                         WSACleanup();  150                         return -1;  151                     }  152                 }  153             }  154      155             break;  156         }  157     } 

1.

#include <winsock2.h>             //winsock.h (2种套接字版本)
#pragma comment(lib,"ws2_32.lib") //wsock32.lib

2.

retVal=ioctlsocket(sServer,FIONBIO,(u_long *)&imode); //第3个参数通常设为1(同时第2个参数设为FIONBIO),表示非阻塞模式

3.

a. //绑定套接字并将其设置为监听状态
 SOCKADDR_IN addrServ;
 addrServ.sin_family=AF_INET;
 addrServ.sin_port  =htons(5000);
 addrServ.sin_addr.S_un.S_addr=inet_addr("192.168.0.102");

 retVal=bind(sServer,(SOCKADDR *)&addrServ,sizeof(addrServ)); //绑定套接字到某一个具体的服务器

这一段代码表明,bind函数需要定义一个addrServ,并且要为每个字段赋值。

b. retVal=listen(sServer,1); //第二个参数,表示最大连接数目

4.

//接受连接
 sockaddr_in addrClient; //定义一个临时地址,用于接受连接(注意:某个客户端由Client.cpp确定)
 int len=sizeof(sockaddr_in);

 SOCKET sClient;
 int errcode;

 while(true)
 {
  sClient=accept(sServer,(sockaddr *)&addrClient,&len);
  if(sClient == INVALID_SOCKET)
  {
   errcode=WSAGetLastError();
   if(errcode == WSAEWOULDBLOCK)  //表示没有客户端发起连接,继续循环
   {

……

5.

retVal=recv(sClient,buf,strlen(buf),0);//第4个参数,表示影响该函数的行为(通常设为0)

retVal=send(sClient,buf,strlen(buf),0); //a.回显接收数据;b.第四个参数:0?

------------------------------------------------------------------------------------------------

1.

addrServ.sin_port  =htons(5000); //为什么要使用htons宏?前者的字段类型和宏的返回值类型一致
 addrServ.sin_addr.S_un.S_addr=inet_addr("192.168.0.102"); //同理,后者函数的返回值类型和字段类型一致

2.
  //scanf(buf); //问题①:为何这两个发送字符串我发送不了?
  //cin>>buf;

  strcpy(buf,"Hello TCP!"); //发送固定字符串

3.

问题②:下次继续做实验,bind failed的原因,而且是Client.cpp端出现的 真奇怪?(自己有调试,结果发现port字段和自己设置的不一致,不知为何)

http://qxzbgzh.blog.51cto.com/blog/2821013/875991