while(1)
{
//if(m_clnLimit < 5)
//{ sockConn = accept(sockSrv,(SOCKADDR*)&addrClient,&len);
if(sockConn != SOCKET_ERROR)
{
sockConnThread = sockConn;
LPVOID conveySock = &sockConnThread;
AfxBeginThread(ConnThread,conveySock);
}
//}
Sleep(100);


}以上是接收连接的循环。UINT CFSendSvrDlg::ConnThread(PVOID pVoid)
{

SOCKET sockConn;
sockConn = (*(SOCKET*)pVoid);
CString strSock;
strSock.Format("%d",sockConn);
::MessageBox(NULL,strSock,"connSock",MB_OK);

}这是具体连接线程的内容。
客户端的连接如下:
while (RecvErr ==1)
{
closesocket(clientSocket);
Sleep(1000);
clientSocket=socket(AF_INET,SOCK_STREAM,0);
ConnRet = connect(clientSocket,(SOCKADDR*)&svrSock,sizeof(SOCKADDR));
客户端的收发如果出错,就循环重新CONNECT。为什么多开几个客户端,只有最后一个能接收到数据,而前面的都不行。而且服务器不断通过MESSAGEBOX报的SOCKET,都是重复循环的?

解决方案 »

  1.   

    你的循环连接里面有没有把RecvErr赋值啊?如果连接成功就要把它赋值啊另外,服务器是否每个socket都发送了数据?
      

  2.   

    UINT CFSendSvrDlg::svrThread(PVOID pVoid)
    {
    WSADATA wsaData;
    int err;
    err = WSAStartup(0x101,&wsaData);
    //AfxBeginThread(InspectThread,NULL);

    SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6124);
    bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
    listen(sockSrv,5); SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);
    SOCKET sockConn;
    SOCKET sockConnThread;
    while(1)
    {
    if(m_clnLimit < 5)
    { sockConn = accept(sockSrv,(SOCKADDR*)&addrClient,&len);
    if(sockConn != SOCKET_ERROR)
    {
    sockConnThread = sockConn;
    LPVOID conveySock = &sockConnThread;
    AfxBeginThread(ConnThread,conveySock);
    }
    }
    Sleep(100);


    }
    WSACleanup();
    return 0;

    }UINT CFSendSvrDlg::ConnThread(PVOID pVoid)
    {

    SOCKET sockConn;
    sockConn = (*(SOCKET*)pVoid);
    CString strSock;
    strSock.Format("%d",sockConn);

    m_clnLimit ++;
    ::MessageBox(NULL,strSock,"connSock",MB_OK);
    char recvFileName[256] = {0};
    recv(sockConn,recvFileName,256,0);
    CString strFileName("d:\\SendFiles\\");
    CString strAdd(recvFileName);
    strFileName+=strAdd; FileInfo fi;
    fi.pFileContext = new char [MAXLENGTH];
    memset(fi.pFileContext,0,MAXLENGTH);


    CFile mFile;
    if(mFile.Open(strFileName,CFile::modeRead)!=FALSE)
    {
    fi.filelen = mFile.GetLength();
    mFile.Read(fi.pFileContext,fi.filelen);
    mFile.Close();
    if(send(sockConn,(char*)&fi.filelen,4,0)==SOCKET_ERROR)
    {
    closesocket(sockConn);
    delete fi.pFileContext;
    m_clnLimit --;
    return 0;
    }; if(send(sockConn,fi.pFileContext,fi.filelen,0)==SOCKET_ERROR)
    {
    closesocket(sockConn);
    delete fi.pFileContext;
    m_clnLimit --;
    return 0;
    };
    }

    closesocket(sockConn);
    delete fi.pFileContext;
    m_clnLimit --;
    return 0;
    }
      

  3.   

    UINT CFRecvClnDlg::ConnThread(PVOID pVoid)
    {
    MessageBeep(0);
    char pcFileNam[256] = {0};
    strncpy(pcFileNam,(char*)pVoid,256); WORD versionRequired;
    WSADATA wsaData;
    versionRequired=MAKEWORD(1,1);
    int err=WSAStartup(versionRequired,&wsaData);
    if(err)
    {
    AfxMessageBox("WSA failed");
    return 1;
    }
    CString strSvrIP;
    ::GetPrivateProfileString("serverip","svrip","127.0.0.1",strSvrIP.GetBuffer(254),254,"d:\\sendfiles\\svrip.ini");
    strSvrIP.ReleaseBuffer();
    ::MessageBox(NULL,strSvrIP,"svrip",MB_OK); SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN svrSock;
    svrSock.sin_addr.S_un.S_addr=inet_addr(strSvrIP);
    svrSock.sin_family=AF_INET;
    svrSock.sin_port=htons(6124);

    FileInfo fi;
    fi.pFileContext = new char [MAXLENGTH];

    memset(fi.pFileContext,0,MAXLENGTH);
     
    char fileName[256] = {0};
    strncpy(fileName,pcFileNam,256);
    CString strFileName("d:\\RecvFiles\\");
    CString strAdd(fileName);
    strFileName += strAdd;
    char * pchContext = fi.pFileContext; int getcount ;
    int recvCount;
    int RecvErr = 1;
    int ConnRet;

    while (RecvErr ==1)
    {
    closesocket(clientSocket);
    Sleep(1000);
    clientSocket = INVALID_SOCKET;
    while (clientSocket ==INVALID_SOCKET)
    {
    clientSocket=socket(AF_INET,SOCK_STREAM,0);
    Sleep(10);
    }

    ConnRet = connect(clientSocket,(SOCKADDR*)&svrSock,sizeof(SOCKADDR));
    if (ConnRet == SOCKET_ERROR)
    {
    RecvErr = 1;

    }
    else
    {
    fi.filelen = 0;
    pchContext = fi.pFileContext;
    send(clientSocket,(char*)pVoid,256,0);
    recv(clientSocket,(char*)&fi.filelen,4,0);
    getcount = fi.filelen;
    recvCount = 0;
    while(getcount > 0)
    {
    recvCount = recv(clientSocket,pchContext,100000,0);
    if (recvCount == SOCKET_ERROR||recvCount == 0)
    {
    RecvErr = 1;
    break;
    }
    else
    {
    getcount -= recvCount;
    pchContext += recvCount;
    RecvErr = 0;
    }

    }
    }
    }
    m_stFlag = 1;
    CFile mFile;
    mFile.Open(strFileName,CFile::modeCreate|CFile::modeWrite);
    mFile.Write(fi.pFileContext,fi.filelen);
    delete fi.pFileContext;

    ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(),USERUPDATE,NULL,NULL); closesocket(clientSocket);
    return 0;
    }
      

  4.   

    程序结构很简单,服务器就加了两个函数,一个是svrThread在窗口初始化时启动,另一个是ConnThread在svrThread里面启动。客户端就一个函数ConnThread,由按钮启动。
      

  5.   

    地址传递问题
     
    sockConnThread = sockConn; 
    LPVOID conveySock = &sockConnThread; 
    AfxBeginThread(ConnThread,conveySock);
    你每次启动线程的时候,都把sockConnThread的地址传进去。由于你这个变量的地址是固定的,也就是说,当你第二次accept的时候,第一个线程中的指针参数所指向的地址中的内容改变了,变成新accept的那个连接。所以说是,后连接的总是可以收到,以前的都收不到。你可以,传值进去
    最好是,建立一个结构体,记录每一个连接上来的客户的相关信息,把这个地址传到线程中。
      

  6.   

    建立一个socket数组应该就行了。
      

  7.   

    会不会是SOCKET的BUG?就是说同一机器,某进程开了一个SOCKET然后关闭,然后很快又开,可能得到一样的SOCKET,导致与其连接的机器仍然以为是之前的那个SOCKET?
      

  8.   

    不可能,哪能让你这么随便弄下,就出来个bug。你说那个收不到了,自己加printf();打印信息,以事实说话,看看究竟是何原因。
    1、看线程死了没
    2、看socket的值,和创建时候的一样不
    自己加加,看看
      

  9.   

    1、线程应没事,因为写入文件在线程后面部分;
    2、只开两个客户端,在服务器那的显示是不同SOCKET。如果这两个客户端自我判断未接收完文件就重新开SOCKET,那么在服务器那会出现重复的SOCKET号反复出现。
    有点晕了,要不你帮我调调吧,QQ:99859454
      

  10.   

    如果只传SOCKET到线程中
    不用这么取地址吧,
    毕竟传局部变量的地址给线程是比较危险的这样就行了
    if(sockConn != SOCKET_ERROR) 

    AfxBeginThread(ConnThread,(LPVOID)sockConn); 
    }
    UINT CFSendSvrDlg::ConnThread(PVOID pVoid) 

    SOCKET sockConn = (SOCKET)pVoid;
    ...
      

  11.   

    另外 accept 出错的返回值是INVALID_SOCKET
      

  12.   

    你这是要干什么?
    你客户端的线程发了个名字过去,然后取回来一段东西保存。然后线程结束、服务端的线程也结束。你这个线程相关的流程就结束了,socket也close了。
    这一切就结束了,再以后发生啥和这有啥关系。
      

  13.   

    初步认为原因如下:
    给线程传送的是一个字符串指针,该指针在几个地方用到,分别是strncpy和send里面,怀疑是该指针在多处用到导致出错。基本上可以结贴了,再看看有没有点评什么的。
      

  14.   

    好久没搞这些东西了,忙学习其他的去了,回头看看。
    这里有个比较突出的问题是SOCKET的关闭问题,一端单方面CLOSESOCKET,另一方如果没有及时做出处理或者反应,那就会出现各种问题了。