user-0 提问: 关于closesocket()关闭套节字传递EOF的问题

回复:
user: user-1
content: 我一般recv 返回小于等于0 就认为断开了。。大于0才表示有数据。

user: user-0
content: 原书的代码贴在这里了： 服务器端： #define BUF_SIZE 100 #define MAX_CLNT 256  unsigned WINAPI HandleClnt(void * arg); void SendMsg(char * msg, int len); void ErrorHandling(char * msg);  int clntCnt=0; SOCKET clntSocks[MAX_CLNT]; HANDLE hMutex;  int main(int argc, char *argv[]) { 	WSADATA wsaData; 	SOCKET hServSock, hClntSock; 	SOCKADDR_IN servAdr, clntAdr; 	int clntAdrSz; 	HANDLE  hThread; 	if(argc!=2) { 		printf("Usage : %s <port>\n", argv[0]); 		exit(1); 	} 	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) 		ErrorHandling("WSAStartup() error!");     	hMutex=CreateMutex(NULL, FALSE, NULL); 	hServSock=socket(PF_INET, SOCK_STREAM, 0);  	memset(&servAdr, 0, sizeof(servAdr)); 	servAdr.sin_family=AF_INET;  	servAdr.sin_addr.s_addr=htonl(INADDR_ANY); 	servAdr.sin_port=htons(atoi(argv[1])); 	 	if(bind(hServSock, (SOCKADDR*) &servAdr, sizeof(servAdr))==SOCKET_ERROR) 		ErrorHandling("bind() error"); 	if(listen(hServSock, 5)==SOCKET_ERROR) 		ErrorHandling("listen() error"); 	 	while(1) 	{ 		clntAdrSz=sizeof(clntAdr); 		hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr,&clntAdrSz); 		 		WaitForSingleObject(hMutex, INFINITE); 		clntSocks[clntCnt++]=hClntSock; 		ReleaseMutex(hMutex); 	 		hThread= 			(HANDLE)_beginthreadex(NULL, 0, HandleClnt, (void*)&hClntSock, 0, NULL); 		printf("Connected client IP: %s \n", inet_ntoa(clntAdr.sin_addr)); 	} 	closesocket(hServSock); 	WSACleanup(); 	return 0; } 	 unsigned WINAPI HandleClnt(void * arg) { 	SOCKET hClntSock=*((SOCKET*)arg); 	int strLen=0, i; 	char msg[BUF_SIZE]; 	 	while((strLen=recv(hClntSock, msg, sizeof(msg), 0))!=0) 		SendMsg(msg, strLen); 	 		 	 	WaitForSingleObject(hMutex, INFINITE); 	for(i=0; i<clntCnt; i++)   // remove disconnected client 	{ 		if(hClntSock==clntSocks[i]) 		{ 			while(i++<clntCnt-1) 				clntSocks[i]=clntSocks[i+1]; 			break; 		} 	} 	clntCnt--; 	ReleaseMutex(hMutex); 	closesocket(hClntSock); 	return 0; } void SendMsg(char * msg, int len)   // send to all { 	int i; 	WaitForSingleObject(hMutex, INFINITE); 	for(i=0; i<clntCnt; i++) 		send(clntSocks[i], msg, len, 0);  	ReleaseMutex(hMutex); } void ErrorHandling(char * msg) { 	fputs(msg, stderr); 	fputc('\n', stderr); 	exit(1); }  客户端： #define BUF_SIZE 100 #define NAME_SIZE 20 	 unsigned WINAPI SendMsg(void * arg); unsigned WINAPI RecvMsg(void * arg); void ErrorHandling(char * msg); 	 char name[NAME_SIZE]="[DEFAULT]"; char msg[BUF_SIZE]; 	 int main(int argc, char *argv[]) { 	WSADATA wsaData; 	SOCKET hSock; 	SOCKADDR_IN servAdr; 	HANDLE hSndThread, hRcvThread; 	if(argc!=4) { 		printf("Usage : %s <IP> <port> <name>\n", argv[0]); 		exit(1); 	} 	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) 		ErrorHandling("WSAStartup() error!");   	sprintf(name, "[%s]", argv[3]); 	hSock=socket(PF_INET, SOCK_STREAM, 0); 	 	memset(&servAdr, 0, sizeof(servAdr)); 	servAdr.sin_family=AF_INET; 	servAdr.sin_addr.s_addr=inet_addr(argv[1]); 	servAdr.sin_port=htons(atoi(argv[2])); 	   	if(connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR) 		ErrorHandling("connect() error"); 	 	hSndThread= 		(HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL); 	hRcvThread= 		(HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);  	WaitForSingleObject(hSndThread, INFINITE); 	WaitForSingleObject(hRcvThread, INFINITE); 	closesocket(hSock); 	WSACleanup(); 	return 0; } 	 unsigned WINAPI SendMsg(void * arg)   // send thread main { 	SOCKET hSock=*((SOCKET*)arg); 	char nameMsg[NAME_SIZE+BUF_SIZE]; 	while(1)  	{ 		fgets(msg, BUF_SIZE, stdin); 		if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n"))  		{ 			closesocket(hSock); 			exit(0); 		} 		sprintf(nameMsg,"%s %s", name, msg); 		send(hSock, nameMsg, strlen(nameMsg), 0); 	} 	return 0; } 	 unsigned WINAPI RecvMsg(void * arg)   // read thread main { 	int hSock=*((SOCKET*)arg); 	char nameMsg[NAME_SIZE+BUF_SIZE]; 	int strLen; 	while(1) 	{ 		strLen=recv(hSock, nameMsg, NAME_SIZE+BUF_SIZE-1, 0); 		if(strLen==-1)  			return -1; 		nameMsg[strLen]=0; 		fputs(nameMsg, stdout); 	} 	return 0; } 	 void ErrorHandling(char *msg) { 	fputs(msg, stderr); 	fputc('\n', stderr); 	exit(1); }