小弟初学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;
}
部分代码:
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;
}
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;
}
如果发生错误则返回SOCKET_ERROR;
所以你要增加ret ==0 的判断
<<WINDOWS 网络编程>> (第2版) 清华大学出版社
Anthony Jones, Jim Ohlund 著
杨合庆 译
这本书不错,有一章对网络连接的各种模型进行比较
else if(ret ==0)
{
std::cout<<"Peer closed!\n";
closesocket(sock);
break;
}
还不行?
能给我就是简单的单对单的send和receive的例子吗?要双方都可发送和接收的,GDI的也行,不要MFC的,小弟谢先