小弟初学socket编程,试做了一个程序,老出问题。具体的就是在一方退出后,另一方得到一些无效数据,怎么避免这一情况,还有各位高手能否介绍好一点的学TCP/IP编程的书,需要在Windows下的开发。
部分代码:
DWORD WINAPI ReceiveThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
int ret=0;
char buf[256];
for(;;)
{
if(flag)
break;
ret=recv(sock,buf,256,0);
if(ret==SOCKET_ERROR)
{
std::cout<<"Receive error!\n";
closesocket(sock);
}
buf[ret]='\0';
std::cout<<buf<<"\n";
}
shutdown(sock,SD_BOTH);
return 0;
}DWORD WINAPI SendThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
int ret=0;
char buf[256];
for(;;)
{
scanf("%s",buf);
//std::cin>>buf;
ret=send(sock,buf,strlen(buf),0);
if(ret==SOCKET_ERROR)
{
std::cout<<"Send error!\n";
return -1;
}
if(!strcmp("quit",buf))
{
flag=true;
break;
}
}
shutdown(sock,SD_BOTH);
SetEvent(Event);
return 0;
}DWORD WINAPI ListenThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
int ret=listen(sock,5);
if(ret==SOCKET_ERROR)
{
std::cout<<"Listen error!\n";
return 0;
}
SOCKET ns=accept(sock,NULL,NULL);
DWORD ReceiveThreadID,SendThreadID;
//ReceiveThreadHandle=
::CreateThread(NULL,0,ReceiveThread,(LPVOID)ns,0,&ReceiveThreadID);
::CreateThread(NULL,0,SendThread,(LPVOID)ns,0,&SendThreadID);
return 0;
}int _tmain(int argc, _TCHAR* argv[])
{
Event=
::CreateEvent(0,0,0,"client_event");
WSADATA wsaDATA;
int ret=WSAStartup(MAKEWORD(2,0),&wsaDATA);
if(ret!=0)
std::cout<<"Initilize error!\n"; SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==SOCKET_ERROR)
std::cout<<"Socket create error!\n"; sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=INADDR_ANY;
addr.sin_port=htons(1028); ret=bind(sock,(LPSOCKADDR)&addr,sizeof(addr));
if(ret==SOCKET_ERROR)
std::cout<<"Socket bind error!\n";
else
{
DWORD ListenThreadID;
::CreateThread(NULL,0,ListenThread,(LPVOID)sock,0,&ListenThreadID);
WaitForSingleObject(Event,INFINITE);
/*DWORD Exit_Code;
GetExitCodeThread(ReceiveThreadHandle,&Exit_Code);
TerminateThread(ReceiveThreadHandle,Exit_Code);*/
} ret=closesocket(sock);
if(ret!=0)
std::cout<<"Error occurs!"; if(WSACleanup()!=0)
std::cout<<"Uninitilize error!\n";
std::cout<<"Threads exit!\n";
getch();
return 0;
}
另一端:
DWORD WINAPI ReceiveThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
int ret=0;
char buf[256];
for(;;)
{
if(flag)
break;
ret=recv(sock,buf,256,0);
if(ret==SOCKET_ERROR)
{
std::cout<<"Receive error!\n";
closesocket(sock);
}
buf[ret]='\0';
std::cout<<buf<<"\n";
}
shutdown(sock,SD_BOTH);
return 0;
}DWORD WINAPI SendThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
int ret=0;
char buf[256];
for(;;)
{
scanf("%s",buf);
//std::cin>>buf;
ret=send(sock,buf,strlen(buf),0);
if(ret==SOCKET_ERROR)
{
std::cout<<"Send error!\n";
return -1;
}
if(!strcmp("quit",buf))
{
flag=true;
break;
}
}
shutdown(sock,SD_BOTH);
SetEvent(Event);
return 0;
}int _tmain(int argc, _TCHAR* argv[])
{
Event=
::CreateEvent(0,0,0,"client_event");
WSADATA wsaDATA;
int ret=WSAStartup(MAKEWORD(2,0),&wsaDATA);
if(ret!=0)
std::cout<<"Initilize error!\n"; SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==SOCKET_ERROR)
std::cout<<"Socket create error!\n";
    
std::cout<<"请输入对方IP地址。\n";
char ip[30];
std::cin>>ip;
sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=inet_addr(ip);
addr.sin_port=htons(1028); ret=connect(sock,(LPSOCKADDR)&addr,sizeof(addr));
if(ret==SOCKET_ERROR)
std::cout<<"Connect error!\n";
else
{
std::cout<<"Connect complete!\n";
DWORD ReceiveThreadID,SendThreadID;
//HANDLE ReceiveThreadHandle=
::CreateThread(NULL,0,ReceiveThread,(LPVOID)sock,0,&ReceiveThreadID);
::CreateThread(NULL,0,SendThread,(LPVOID)sock,0,&SendThreadID);
WaitForSingleObject(Event,INFINITE);
/*DWORD Exit_Code;
GetExitCodeThread(ReceiveThreadHandle,&Exit_Code);
TerminateThread(ReceiveThreadHandle,Exit_Code);*/
} ret=closesocket(sock);
if(ret!=0)
std::cout<<"Error occurs!";

if(WSACleanup()!=0)
std::cout<<"Uninitilize error!\n";
std::cout<<"Threads exit!\n";
getch();
return 0;
}

解决方案 »

  1.   

    代码很多看得头疼不过如果一方退出后加上while(recv()>0)应该可以避免你的问题
      

  2.   

    将如下代码
                      ret=recv(sock,buf,256,0);
    if(ret==SOCKET_ERROR)
    {
    std::cout<<"Receive error!\n";
    closesocket(sock);
    }
    改成
                      ret=recv(sock,buf,256,0);
    if(ret==SOCKET_ERROR)
    {
    std::cout<<"Receive error!\n";
    closesocket(sock);
                                break; // add this break
    }
                      else if(ret ==0)
                      {
    std::cout<<"Peer closed!\n";
    closesocket(sock);
                                break;
                      }
      

  3.   

    如果连接断开recv返回值为0;
    如果发生错误则返回SOCKET_ERROR;
    所以你要增加ret ==0 的判断
    <<WINDOWS 网络编程>> (第2版) 清华大学出版社 
    Anthony Jones, Jim Ohlund 著
    杨合庆 译
    这本书不错,有一章对网络连接的各种模型进行比较
      

  4.   

    mscf(扎西特勒) , 你的问题还没解决? 加了                  
                      else if(ret ==0)
                      {
    std::cout<<"Peer closed!\n";
    closesocket(sock);
                                break;
                      }
    还不行?
      

  5.   

    对方收到若干空字符,我指的什么都看不到,被换若干行,我的程序在写法上也不规范,我只是想到哪里就写到哪里。
    能给我就是简单的单对单的send和receive的例子吗?要双方都可发送和接收的,GDI的也行,不要MFC的,小弟谢先
      

  6.   

    小弟依妹儿:[email protected]