又是IOCP 的 10038 .第二次接收出错.

时间:2021-04-03 09:04:48
在服务器端里.第一次接收是正常的.但在接收第二次的时候出现10038.说ClientSocket 不是套接字.实在有点搞不懂了.望高人指教.
服务器端的大体代码.代码是我做测试是使用.结构不好.


#define PORT 1130
#define MAXSIZE 1024
#define null NULL

struct OVERPROT
{
   int        xvier;
   OVERLAPPED Overlapped;
   WSABUF DataBuf; // 接收数据的缓冲区
   CHAR Buffer[MAXSIZE];              
   DWORD BytesSEND;                 // 发送字节数
   DWORD BytesRECV; // 接收的字节数.
   SOCKET server; // 服务器的socket;
   SOCKET client; // 客户端的socket;
};

SOCKET *wparam = null;
OVERPROT *overprot = null;

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);

int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
if(::WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
{
cout<<"WSAStratup function exception!"<<endl;
return -1;
}

HANDLE completionport = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
if(completionport == NULL)
{
cout<<"CreateIoCompletionPort function exception"<<endl;
goto Exit;
}

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == SOCKET_ERROR)
{
cout<<"socket function exception"<<endl;
goto Exit;
}

DWORD dword=0;
HANDLE thread =::CreateThread(NULL,0,ServerWorkerThread,completionport,0,&dword);
if(thread == null)
{
cout<<"CreateThread function exception"<<endl;
goto Exit;
}

SOCKADDR_IN sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr.sin_port = htons(PORT); 

if(::bind(sock,(PSOCKADDR)&sockaddr,sizeof(sockaddr)) == SOCKET_ERROR)
{
cout<<"bind function exception"<<endl;
goto Exit;
}

if(::listen(sock,50) == SOCKET_ERROR)
{
cout<<"listen function exception"<<endl;
goto Exit;
}

while(TRUE)
{
SOCKET client = ::WSAAccept(sock,NULL,NULL,NULL,0);
if(client == SOCKET_ERROR)
{
cout<<"Accept function exception"<<endl;
goto Exit;
}

overprot = (OVERPROT *)::GlobalAlloc(GPTR,sizeof(OVERPROT));
if(overprot == null)
{
cout<<"GlobalAlloc OVERPTOR function exception"<<endl;
goto Exit;
}

memset(&overprot->Overlapped,0,sizeof(OVERLAPPED));
overprot->BytesRECV = 0;
overprot->BytesSEND = 0;
overprot->DataBuf.buf = overprot->Buffer;
overprot->DataBuf.len = MAXSIZE;
overprot->server = sock;
overprot->client = client;


if(::CreateIoCompletionPort((HANDLE)client,completionport,(DWORD)overprot,0) == NULL)
{
cout<<"CreateIocompletionPort function bind socket excetion"<<endl;
goto Exit;
}

DWORD RecvBytes,flast=0;
                // 这次接收是正常的.
if (WSARecv(client, &(overprot->DataBuf), 1, &RecvBytes, &flast, 
&(overprot->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
goto Exit;
}
}
}

Exit:
if(overprot != NULL) ::GlobalFree(overprot);
if(thread != NULL) ::CloseHandle(thread);
if(sock != SOCKET_ERROR) ::closesocket(sock);
if(completionport != NULL) ::CloseHandle(completionport);
::WSACleanup();
return 0;
}

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD dwBytesXfered;
LONG_PTR PerHandleKey;
OVERPROT *overlap ;
DWORD RecvBytes,flast=0;

while(true)
{
    int ret = GetQueuedCompletionStatus(
            CompletionPort,
            &dwBytesXfered,
            (PULONG_PTR)&PerHandleKey,
            (LPOVERLAPPED  *)&overlap,
            INFINITE);
               if (ret == 0)
               {
                  continue;
               }
// 第一次接收是能取得数据的.
// cout<<"Data length"<< dwBytesXfered<<endl;
// cout<<"DataBuffer "<<overlap->Buffer<<endl;
// cout<<"Recv length "<<overlap->BytesRECV <<endl;
// cout<<"Send length "<<overlap->BytesSEND<<endl;


memset(&(overlap->Overlapped),0,sizeof(OVERLAPPED));
overprot->BytesRECV = 0;
overprot->BytesSEND = 0;
overprot->DataBuf.buf = overprot->Buffer;
overprot->DataBuf.len = MAXSIZE;

// 但在这次接收的时候,确报10038 . 在主线程中也是用了这个 client socket了.但又没错
if (WSARecv(overlap->client, &(overprot->DataBuf), 1, &RecvBytes, &flast, 
&(overprot->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
}
}

}
return 0;
}


客户端很简单只是发送字符串,用C#写的.代码如下:

        static void Main(string[] args)
        {
            IPHostEntry localhost = Dns.GetHostEntry(Dns.GetHostName());
            IPEndPoint ipend = new IPEndPoint(localhost.AddressList[0].Address, 1130);

            int sendcount = 99;
            byte[] bytebuffer = new byte[1024];
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(ipend);

            while ((sendcount--)>0)
            {
                string strbuffer = "Hello world! Say time:" + DateTime.Now.ToString();
                bytebuffer = Encoding.ASCII.GetBytes(strbuffer);
                int v=client.Send(bytebuffer);
                Console.Write("Send Count {0} \n {1}", sendcount, strbuffer);
                Thread.Sleep(99);
            }

            client.Shutdown(SocketShutdown.Both);
            client.Close();

            Console.Read();
        }

6 个解决方案

#1


没找到ClientSocket

#2


可以 Client Socket  我在主线程中加进去了啊.

        overprot = (OVERPROT *)::GlobalAlloc(GPTR,sizeof(OVERPROT));
        if(overprot == null)
        {
            cout<<"GlobalAlloc OVERPTOR function exception"<<endl;
            goto Exit;
        }

        memset(&overprot->Overlapped,0,sizeof(OVERLAPPED));
        overprot->BytesRECV = 0;
        overprot->BytesSEND = 0;
        overprot->DataBuf.buf = overprot->Buffer;
        overprot->DataBuf.len = MAXSIZE;
        overprot->server = sock;
        overprot->client = client;
        

        if(::CreateIoCompletionPort((HANDLE)client,completionport,(DWORD)overprot,0) == NULL)
        {
            cout<<"CreateIocompletionPort function bind socket excetion"<<endl;
            goto Exit;
        }

在线程中.的WSARecv 函数中我下了断点.看到client socket 并不为 0 啊.

#3


楼主,严谨些

但在接收第二次的时候出现10038.说ClientSocket 不是套接字

#4


while(TRUE)
    {
        SOCKET client = ::WSAAccept(sock,NULL,NULL,NULL,0);
        if(client == SOCKET_ERROR)
        {
            cout<<"Accept function exception"<<endl;
            goto Exit;
        }

        overprot = (OVERPROT *)::GlobalAlloc(GPTR,sizeof(OVERPROT));
        if(overprot == null)
        {
            cout<<"GlobalAlloc OVERPTOR function exception"<<endl;
            goto Exit;
        }

        memset(&overprot->Overlapped,0,sizeof(OVERLAPPED));
        overprot->BytesRECV = 0;
        overprot->BytesSEND = 0;
        overprot->DataBuf.buf = overprot->Buffer;
        overprot->DataBuf.len = MAXSIZE;
        overprot->server = sock;
        overprot->client = client;
        

        if(::CreateIoCompletionPort((HANDLE)client,completionport,(DWORD)overprot,0) == NULL)
        {
            cout<<"CreateIocompletionPort function bind socket excetion"<<endl;
            goto Exit;
        }

        DWORD RecvBytes,flast=0;
                // 这次接收是正常的.
        if (WSARecv(client, &(overprot->DataBuf), 1, &RecvBytes, &flast, 
            &(overprot->Overlapped), NULL) == SOCKET_ERROR)
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                goto Exit;
            }
        }
    }

在第二次进去循环时,client已经变了啊

#5


......谢谢.ouyh12345. 我闷了.....我知道错在那里了.谢谢....深刻的教训.

#6


为什么client在进第二次循环的时候就变了呢????

#1


没找到ClientSocket

#2


可以 Client Socket  我在主线程中加进去了啊.

        overprot = (OVERPROT *)::GlobalAlloc(GPTR,sizeof(OVERPROT));
        if(overprot == null)
        {
            cout<<"GlobalAlloc OVERPTOR function exception"<<endl;
            goto Exit;
        }

        memset(&overprot->Overlapped,0,sizeof(OVERLAPPED));
        overprot->BytesRECV = 0;
        overprot->BytesSEND = 0;
        overprot->DataBuf.buf = overprot->Buffer;
        overprot->DataBuf.len = MAXSIZE;
        overprot->server = sock;
        overprot->client = client;
        

        if(::CreateIoCompletionPort((HANDLE)client,completionport,(DWORD)overprot,0) == NULL)
        {
            cout<<"CreateIocompletionPort function bind socket excetion"<<endl;
            goto Exit;
        }

在线程中.的WSARecv 函数中我下了断点.看到client socket 并不为 0 啊.

#3


楼主,严谨些

但在接收第二次的时候出现10038.说ClientSocket 不是套接字

#4


while(TRUE)
    {
        SOCKET client = ::WSAAccept(sock,NULL,NULL,NULL,0);
        if(client == SOCKET_ERROR)
        {
            cout<<"Accept function exception"<<endl;
            goto Exit;
        }

        overprot = (OVERPROT *)::GlobalAlloc(GPTR,sizeof(OVERPROT));
        if(overprot == null)
        {
            cout<<"GlobalAlloc OVERPTOR function exception"<<endl;
            goto Exit;
        }

        memset(&overprot->Overlapped,0,sizeof(OVERLAPPED));
        overprot->BytesRECV = 0;
        overprot->BytesSEND = 0;
        overprot->DataBuf.buf = overprot->Buffer;
        overprot->DataBuf.len = MAXSIZE;
        overprot->server = sock;
        overprot->client = client;
        

        if(::CreateIoCompletionPort((HANDLE)client,completionport,(DWORD)overprot,0) == NULL)
        {
            cout<<"CreateIocompletionPort function bind socket excetion"<<endl;
            goto Exit;
        }

        DWORD RecvBytes,flast=0;
                // 这次接收是正常的.
        if (WSARecv(client, &(overprot->DataBuf), 1, &RecvBytes, &flast, 
            &(overprot->Overlapped), NULL) == SOCKET_ERROR)
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                goto Exit;
            }
        }
    }

在第二次进去循环时,client已经变了啊

#5


......谢谢.ouyh12345. 我闷了.....我知道错在那里了.谢谢....深刻的教训.

#6


为什么client在进第二次循环的时候就变了呢????