遇到一SOCKET 10038无效SOCKET 错误,在网上查了好长时间,仍没能解决,大家指点啊。。。。

本文通过一个详细的Winsock异步IO示例,展示了如何使用重叠结构和完成端口来实现高效的网络通信。包括服务器端和客户端的代码解析,以及在实际运行中可能遇到的SOCKET_ERROR问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

server :

 

 

 

#define RECV_POSTED 0
#define SEND_POSTED 1

char Buffer[1024];


typedef struct _PER_HANDLE_DATA
{
 SOCKET Socket;  //该结构是用于向端口传送套接字的
}PER_HANDLE_DATA,*LPER_HANDLE_DATA;


typedef struct _PER_IO_DATA
{
 OVERLAPPED  Overlapped;
 WSABUF      WsaBuffer;
 DWORD       RecvByte,SendByte;
 int         OperationType;

}PER_IO_DATA,*LPER_IO_DATA;

 

//*********************************************************************************
//  ServerWorkThread............
//*********************************************************************************
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
 HANDLE            CompletionPort  =(HANDLE)CompletionPortID;
 DWORD             BytesTransferred;
 PER_IO_DATA      PerIoData;
 PER_HANDLE_DATA  PerHandleData;
 DWORD             Flags;
 WSAEVENT     EventArray[WSA_MAXIMUM_WAIT_EVENTS];
 DWORD         totalEvent=0;
 DWORD      indexEvent;
 while(TRUE)
 {
  if(GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,
   (LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIoData,INFINITE)==NULL)
  {
   printf("wait error...errorcode:%d",WSAGetLastError());
//等待失败!错误:WSAGetLastError()
      continue;
  }
//did not use WSAEvent..................
 /* if(BytesTransferred==0 &&(PerIoData->OperationType==RECV_POSTED
   ||PerIoData->OperationType==SEND_POSTED))
  {
   cout<<"套接字已经关闭!"<<endl;
   closesocket(PerHandleData.Socket);
   GlobalFree(PerHandleData);
   continue;
  }
*/

  EventArray[totalEvent] = WSACreateEvent();
  ZeroMemory(&PerIoData.Overlapped,sizeof(OVERLAPPED));
  PerIoData.WsaBuffer.buf  =Buffer;
  PerIoData.WsaBuffer.len  =2048;
  PerIoData.Overlapped.hEvent=EventArray[totalEvent];
  PerIoData.OperationType  =RECV_POSTED;


  indexEvent = WSAWaitForMultipleEvents(totalEvent, EventArray, FALSE, WSA_INFINITE, FALSE);
  WSAResetEvent(EventArray[indexEvent - WSA_WAIT_EVENT_0]);

    //-----------------------------------------
    // Determine the status of the overlapped event
  WSAGetOverlappedResult(PerHandleData.Socket,&PerIoData.Overlapped, &BytesTransferred, FALSE, &Flags);
  if (BytesTransferred == 0) {
      printf("Closing Socket %d/n", PerHandleData.Socket);
      closesocket(PerHandleData.Socket);
      WSACloseEvent(EventArray[indexEvent - WSA_WAIT_EVENT_0]);
      return 0;
    }

 if(PerIoData.OperationType==RECV_POSTED)
  {
   printf("Recved things is :%s/n",PerIoData.WsaBuffer.buf);
  // 接收到的数据
 }
  //继续接收数据...
 printf("go on  recving........../n");
  if(WSARecv(PerHandleData.Socket,&(PerIoData.WsaBuffer),1,&(PerIoData.RecvByte),&Flags,&(PerIoData.Overlapped),NULL)==SOCKET_ERROR)
  {
   //发送数据失败...
   printf("send error ..errorcode is:%d/n",WSAGetLastError());
   continue;
  }
 }
}
//*********************************************************************************
void main()
{
 HANDLE            CompletionPort;
 WSADATA           WsaData;
 SYSTEM_INFO       SystemInfo;
 SOCKADDR_IN       ServerAddr;
 SOCKADDR_IN       ClientAddr;
 int               ClientAddrLen;
 SOCKET            ListenSocket;
 SOCKET            NewSocket;
 PER_HANDLE_DATA   PerHandleData;//*PerHandleData=NULL;
 PER_IO_DATA       PerIoData;//*PerIoData;
 DWORD             Flags=NULL;
 

 if(WSAStartup(MAKEWORD(2,2),&WsaData)!=NULL) //winsock2
 {
  printf("注册失败!错误是:%d/n",WSAGetLastError());
  ExitProcess(1);
 }

 ListenSocket=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
 if(ListenSocket==INVALID_SOCKET)
 {
  printf("套接字创建失败!/n");
  WSACleanup();
  ExitProcess(1);
 }

//******************************************************************************************
 CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
 if(CompletionPort==INVALID_HANDLE_VALUE)
 {
  printf("创建端口对象错误!/n");
        WSACleanup();
  ExitProcess(1);
 }

 GetSystemInfo(&SystemInfo);                                //获得系统的information
printf("the CPU's num is :%d/n",SystemInfo.dwNumberOfProcessors);
 for(DWORD i=0;i< SystemInfo.dwNumberOfProcessors;i++)     //创建工作器线程的数量是处理器的 2 倍加 2 个
 {
  HANDLE ThreadHandle;

  ThreadHandle=CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL);
  CloseHandle(ThreadHandle);
 }


//bind with server===================================================
 ServerAddr.sin_family      =AF_INET;
 ServerAddr.sin_addr.s_addr =htonl(INADDR_ANY);
 ServerAddr.sin_port        =htons(8000);

 if(bind(ListenSocket,(PSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR)
 {
  printf("套接字绑定错误:%d/n",WSAGetLastError());
  WSACleanup();
  ExitProcess(1);
 }

 if(listen(ListenSocket,5)==SOCKET_ERROR)
 {
  //套接字监听失败!
  printf("listen error ....:%d",WSAGetLastError());
  WSACleanup();
  ExitProcess(1);
 }

 ClientAddrLen=sizeof(ClientAddr);
 while(TRUE)
 {
  printf("listening begin................./n");
  NewSocket=WSAAccept(ListenSocket,(SOCKADDR*)&ClientAddr,&ClientAddrLen,NULL,0);//client_info
  if(NewSocket==INVALID_SOCKET)
  {
   printf("accept error........./n");
   continue;
  }
  //PerHandleData=(LPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));//用globalalloc分配一块
                                                                             //固定的内存,并初始为0 
  printf("收到端口号 %d,地址是%s 的链接!/n",ntohs(ClientAddr.sin_port),
   inet_ntoa(ClientAddr.sin_addr));

  PerHandleData.Socket = NewSocket;
  //PerHandleData->Socket=NewSocket;
//  memcpy(&PerHandleData->ClientAddr,&ClientAddr,ClientAddrLen);
                                                                         //PerHandleData是用于保存用户的SOCKET信息的

  CreateIoCompletionPort((HANDLE)NewSocket,CompletionPort,(DWORD)&PerHandleData,0); 
                                                                        // 完成端口同套接字关联起来
  //PerIoData  =(LPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));

  PerIoData.WsaBuffer.buf =Buffer;
  PerIoData.WsaBuffer.len =sizeof(Buffer);
  PerIoData.OperationType =RECV_POSTED;
  ZeroMemory(&PerIoData.Overlapped,sizeof(PerIoData.Overlapped));
 

  if(WSARecv(NewSocket,&PerIoData.WsaBuffer,1,&PerIoData.RecvByte,&Flags,&(PerIoData.Overlapped),NULL)==SOCKET_ERROR)
  {
   printf("接收数据失败!错误:%d",WSAGetLastError());
   continue;
  }
 }
 printf("server is closed..../n");
 closesocket(NewSocket);
 WSACleanup();
}

.....

 

 

 

 

client :

 

 

#define NO_FLAGS_SET 0
#pragma comment(lib,"ws2_32.lib")
#define PORT (u_short) 8000
#define DEST_IP_ADDR "127.0.0.1" //Server address

int  main(void)
{
  WSADATA Data;
  SOCKADDR_IN destSockAddr;
  SOCKET destSocket;
  unsigned long destAddr;
  int status;
  int numsnt;
  char *toSendtxt="I am Coming............haha";


  status=WSAStartup(MAKEWORD(1, 1), &Data);
  if (status != 0)
 printf("ERROR: WSAStartup unsuccessful/n");
  /* convert IP address into in_addr form */
  destAddr=inet_addr(DEST_IP_ADDR);
  /* copy destAddr into sockaddr_in structure */
  memcpy(&destSockAddr.sin_addr,
    &destAddr, sizeof(destAddr));
  /* specify the port portion of the address */
  destSockAddr.sin_port=htons(PORT);
  /* specify the address family as Internet */
  destSockAddr.sin_family=AF_INET;

  destSocket=socket(AF_INET, SOCK_STREAM, 0);
  if (destSocket == INVALID_SOCKET)
  {
 printf("ERROR: socket unsuccessful/n");
    status=WSACleanup();
    if (status == SOCKET_ERROR)
 printf("ERROR: WSACleanup unsuccessful/n");
    return(1);
  }
printf("Trying to connect to IP Address:%s",DEST_IP_ADDR);

  /* connect to the server */
  status=connect(destSocket,(LPSOCKADDR) &destSockAddr,sizeof(destSockAddr));
  if (status == SOCKET_ERROR)
  {
 printf("ERROR: connect unsuccessful/n");
    status=closesocket(destSocket);
    if (status == SOCKET_ERROR)
  printf("ERROR: closesocket unsuccessful");
    status=WSACleanup();
    if (status == SOCKET_ERROR)
  printf("ERROR: WSACleanup unsuccessful");
    return(1);
  }

printf("Connected.../n" );
  while(1)
  {
   printf("Sending.../n" );
    numsnt=send(destSocket, toSendtxt,strlen(toSendtxt) + 1, NO_FLAGS_SET);
    if (numsnt != (DWORD)strlen(toSendtxt) + 1)
    {
  printf("Connection terminated/n" );
      status=closesocket(destSocket);
      if (status == SOCKET_ERROR)
         printf("ERROR: closesocket unsuccessful/n" );
      status=WSACleanup();
      if (status == SOCKET_ERROR)
    printf("ERROR: WSACleanup unsuccessful/n" );
      return(1);
    }

  /* Wait before sending the message again */
  Sleep(4800);
  } /* while */
}

 

 

遇到一SOCKET 10038无效SOCKET 错误,在网上查了好长时间,仍没能解决,大家指点啊。。。。
在WHILE 处,
为什么第一次收到数据正常,第二次就是SOCKET_ERROR 呢?

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值