DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;
char szBuffer[DEFAULT_BUFFER];
int iRet, nLeft, idx;

while (true)
{
iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
if (0 == iRet)
break;
else if (SOCKET_ERROR == iRet)
{
cout << "recv() failed:" << WSAGetLastError() << endl;
break;
}
szBuffer[iRet] = '\0';
cout << "The Message Resieved: " << szBuffer << endl;
}
cout << "ClientThread exit!" << endl;
return 0;
}
以上是我在接受一个连接以后 创建的一个线程 lpParam 传进来一个accept()反回来的socket 
现在的问题是 客户端发送一次数据 这个服务线程可以接收数据 但是紧接着 在循环中第二次执行recv()时 发生10038(WSAENOTSOCK)错误 为什么呀? recv()只能执行一次???
还请各位指教!

解决方案 »

  1.   

    WSAENOTSOCK                    (10038)             Socket operation on non-socket.操作试图不是在套接字上进行。它可能是套接字句柄参数没有引用到一个合法套接字,或者是调用select()函数时,一个fd_set中的成员不合法。
      

  2.   

    哈哈,你看看我的一个贴子对你有启发的(一样的错误^_^)http://expert.csdn.net/Expert/topic/2457/2457911.xml?temp=.1710321
      

  3.   

    我初学 WinSock
    可是我的好像和你的问题 不大一样!
    我的程序很简单 就是 客户端在控制台接收用户输入的字符串 然后 send给 服务端 然后 服务端 接收 显示!
    可就是出现这个问题!!请问 recv() 第三个参数的用途是什么? 如果 接收的数据 比DEFAULT_BUFFER小 会产生什么结果?? 是不是这个问题 导致 recv()错误!
      

  4.   

    listen(sListen, 4);
    cout << "listening..." << endl; while(true)
    {
    iAddrSize=sizeof(client);
    sClient = accept(sListen, (SOCKADDR *)&client, &iAddrSize);
    if (INVALID_SOCKET == sClient)
    {
    cout << "accept() failed:" << WSAGetLastError() << endl;
    break;
    }
    cout << "accept a connect." << endl;

    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);
    if (NULL == hThread)
    {
    cout << "CreateThread() failed :" << GetLastError() << endl;
    break;
    }
    CloseHandle(hThread);
    }
    以上是我父线程的 代码!
    并没有在父线程里关闭连接!
      

  5.   

    我不知道我说的对不对,仅供参考:
    recv和send是在两端的一对操作,你接受了一个数据之后由于对方未放送新的数据过来,而你的while还在循环,造成不能接受。
    建议使用CreateIoCompletionPort()将数据放入一个队列中,然后用GetQueuedCompletionStatus()取。从各方面来说应该要好一点吧。
      

  6.   

    sckNotSocket 10038 描述符不是套接字。
      

  7.   

    先检查你的(SOCKET)lpParam;
    是否正确?
      

  8.   

    tolixiaohui(I_am_a_job_finder!) :
    我的套接字应该是正确的 因为第一次接受正确!gujianfei1979(谷谷):
    while循环 为什么不能接收? recv不是阻塞的吗? 程序运行到recv 应该阻塞等待呀!
    而现在 它没有阻塞 而是出错了 出在哪里呀??
      

  9.   

    szBuffer[iRet] = '\0'; 这句执行以后 套接字就改变了 为什么?
      

  10.   

    服了!!  看来我得把源程序全贴出来!!
    我说了 程序很简单! 给你们看看吧~~
    我可没有生气 呵呵~~  希望大家帮帮忙吧~~
    已经好几天了 就是解决不了!!
    每次都是在 szBuffer[iRet] = '\0'; 这句执行之后 套接字的值 改变了!服务端!
    // 002.cpp : Defines the entry point for the console application.
    //#include "stdafx.h"
    #include <iostream>
    #include <winsock2.h>using namespace std;#define DEFAULT_PORT 5111
    #define DEFAULT_BUFFER 4096DWORD WINAPI ClientThread(LPVOID lpParam)
    {
    SOCKET sock = (SOCKET)lpParam;
    char szBuffer[DEFAULT_BUFFER];
    int iRet, nLeft, idx;
    cout << "start : " << (int)sock << endl;

    while (true)
    {
    cout << "before recv : " << (int)sock << endl;
    iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
    cout << "after recv : " << (int)sock << endl;
    if (0 == iRet)
    break;
    else if (SOCKET_ERROR == iRet)
    {
    cout << "recv() failed:" << WSAGetLastError() << endl;
    break;
    }
    cout << "after if: " << (int)sock << endl;
    szBuffer[iRet] = '\0';
    cout << "before output : " << (int)sock << endl;
    cout << "The Message Resieved: " << szBuffer << endl;
    cout << "after output : " << (int)sock << endl;
    }
    cout << "ClientThread exit!" << endl;
    return 0;
    }int main(int argc, char* argv[])
    {
    int iRet, iError, iAddrSize;
    SOCKET sListen, sClient;
    sockaddr_in local, client;
    WSAData wsaData;
    HANDLE hThread;
    DWORD dwThreadId; iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (0 != iRet)
    {
    cout << "iRet:" << iRet << endl;
    return 1;
    }
    cout << "WSAStartup()" << endl; sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (SOCKET_ERROR == sListen)
    {
    cout << "socket() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    cout << "socket()" << endl;

    local.sin_addr.s_addr = htonl(INADDR_ANY);
    local.sin_family = AF_INET;
    local.sin_port = htons(DEFAULT_PORT); if (SOCKET_ERROR == bind(sListen, (SOCKADDR *)&local, sizeof(local)))
    {
    cout << "bind() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    cout << "bind()" << endl; listen(sListen, 4);
    cout << "listening..." << endl; while(true)
    {
    iAddrSize=sizeof(client);
    sClient = accept(sListen, (SOCKADDR *)&client, &iAddrSize);
    if (INVALID_SOCKET == sClient)
    {
    cout << "accept() failed:" << WSAGetLastError() << endl;
    break;
    }
    cout << "accept a connect." << endl;

    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);
    if (NULL == hThread)
    {
    cout << "CreateThread() failed :" << GetLastError() << endl;
    break;
    }
    CloseHandle(hThread);
    }
    closesocket(sListen); WSACleanup();
    cout << "socket is closed" << endl;
    return 0;
    }
    客户端:
    // 003.cpp : Defines the entry point for the console application.
    //#include "stdafx.h"
    #include <winsock2.h>
    #include <iostream>using namespace std;#define DEFAULT_PORT 5111
    #define DEFAULT_BUFFER 4096int main(int argc, char* argv[])
    {
    int iRet;
    SOCKET sConnect;
    sockaddr_in saServer;
    WSAData wsaData;
    char strBuffer[DEFAULT_BUFFER] ;//= "asdfierrttsdklfjgka"; iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (0 != iRet)
    {
    cout << "WSAStartup() failed:" << iRet << endl;
    return 1;
    }
    cout << "WSAStartup()" << endl; sConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (SOCKET_ERROR == sConnect)
    {
    cout << "socket() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    cout << "socket()" << endl; saServer.sin_addr.s_addr = inet_addr("192.168.0.1");
    saServer.sin_family = AF_INET;
    saServer.sin_port = htons(DEFAULT_PORT); iRet = connect(sConnect, (SOCKADDR *)&saServer, sizeof(saServer));
    if (SOCKET_ERROR == iRet)
    {
    cout << "connect() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    cout << "connect()" << endl; for (int i = 1; i < 10; i++)
    {
    cin >> strBuffer;

    iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);
    if (SOCKET_ERROR == iRet)
    {
    cout << "send() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    cout << "send() return!" << endl;
    }
    cout << "end" << endl;
    closesocket(sConnect);
    cout << "closesocket() completed!" << endl;
    WSACleanup();
    return 0;
    }很简单是吧! 我是初学者 大家帮忙 看看哪里不对!
      

  11.   

    既然你的第一次连接是正确的,我想也许是其他的原因,
    你试试在client中
    for (int i = 1; i < 10; i++)
    {
    cin >> strBuffer;
    iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);
    if (SOCKET_ERROR == iRet)
    {
    cout << "send() failed:" << WSAGetLastError() << endl;
    return 1;
    }
    //////////////////////
                      sleep(100);
    //////////////
    cout << "send() return!" << endl;
    }
    在server的时候记得在线程中
    while (true)
    {
    cout << "before recv : " << (int)sock << endl;
                       memset(szBuffer,0,DEFAULT_BUFFER);
    iRet = recv(sock, szBuffer, DEFAULT_BUFFER, 0);
    cout << "after recv : " << (int)sock << endl;
    if (0 == iRet)
    break;
    else if (SOCKET_ERROR == iRet)
    {
    cout << "recv() failed:" << WSAGetLastError() << endl;
    break;
    }
    ........
    个人看法,
      

  12.   

    呵呵~~  问题解决了!!
    去掉 szBuffer[iRet] = '\0'; 这句 程序就正常了!!
    问题是 这句是怎么影响到 套接字的呀????
    奇怪了!!  请大家解释一下!!
    还有 我还是弄不明白 recv() send() 这两个函数中 参数的意思 msdn我看了 感觉说得不明白!
    int recv (
      SOCKET s,       
      char FAR* buf,  
      int len,        
      int flags       
    );
    len 这个参数 指的是buf的长度?? 那么 如果接收的数据小与len 结果是什么? buf中存放的数据(假设是字符串)是什么样子的? 他会自动在结尾加上“\0”吗? 返回值 代表什么意思? 是buf中数据的个数吗? 这句szBuffer[iRet] = '\0';(目的是在字符串最后一个字符加上“\0”)为什么出错???
    int send (
      SOCKET s,              
      const char FAR * buf,  
      int len,               
      int flags              
    );
    send中 len代表buf中包含的数据大小 还是buf缓冲区的大小? 如果是数据的大小 那么我的程序iRet = send(sConnect, strBuffer, DEFAULT_BUFFER, 0);这句是不是错了??  如果这句错了 那么是不是因为 len = DEFAULT_BUFFER 导致了传送了 DEFAULT_BUFFER个数据 接收端接收了DEFAULT_BUFFER个数据 使得szBuffer[iRet](iRet = DEFAULT_BUFFER)溢出了 造成了 套接字错误?
      

  13.   

    楼主你的sock操作都是没有错误的。
    问题就是出在szBuffer[iRet] = '\0'上。
    根据你的变量定义
    SOCKET sock = (SOCKET)lpParam;
    char szBuffer[DEFAULT_BUFFER];
    szBuffer[iRet] = '\0'实际上是在sock的地方写了'\0';
    因为在C/C++中,数组是的索引是从0开始的,当你的recv读了DEFAULT_BUFFER个数据后,如果调用szBuffer[DEFAULT_BUFFER] = '\0',实际上就是缓冲区溢出了。建议定义为
    char szBuffer[DEFAULT_BUFFER + 1];
    就好了