2016-02-29 203 views
0

我只是想知道为什么当客户端连接崩溃?它应该是一个简单的TCP服务器,当客户端连接并发送一个字符串时,服务器响应字符串中A的个数。服务器一旦崩溃的客户端类型的一封信TCP服务器崩溃

#include<io.h> 
#include<stdio.h> 
#include<winsock2.h> 

#pragma comment(lib,"ws2_32.lib") //Winsock Library 

int main(int argc , char *argv[]) 
{ 
WSADATA wsa; 
SOCKET s , new_socket, master; 
struct sockaddr_in server , address; 
int c, valread; 
char *message = "Welcome to Marshall's TCP Server!!"; 
int MAXRECV = 1024; 
char *buffer; 
char AmmtA = 'a'; 
char AmmtB = 'A'; 
int count = 0, x; 
fd_set readfds; 
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char)); 

printf("\nInitialising Winsock..."); 
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
{ 
    printf("Failed. Error Code : %d",WSAGetLastError()); 
    return 1; 
} 

printf("Initialised.\n"); 

//Create a socket 
if((s = socket(AF_INET , SOCK_STREAM , 0)) == INVALID_SOCKET) 
{ 
    printf("Could not create socket : %d" , WSAGetLastError()); 
} 

printf("Socket created.\n"); 

//Prepare the sockaddr_in structure 
server.sin_family = AF_INET; 
server.sin_addr.s_addr = INADDR_ANY; 
server.sin_port = htons(9000); 

//Bind 
if(bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) 
{ 
    printf("Bind failed with error code : %d" , WSAGetLastError()); 
    exit(EXIT_FAILURE); 
} 

puts("Bind done"); 

//Listen to incoming connections 
listen(s , 3); 
//Accept and incoming connection 
puts("Waiting for incoming connections..."); 

c = sizeof(struct sockaddr_in); 

while((new_socket = accept(s , (struct sockaddr *)&address, &c)) != INVALID_SOCKET) 
{ 
    puts("Connection accepted"); 

send(new_socket , message , strlen(message) , 0); 

valread = recv(new_socket , buffer, MAXRECV, 0); 

      if(valread == SOCKET_ERROR) 
      { 
       int error_code = WSAGetLastError(); 
       if(error_code == WSAECONNRESET) 
       { 
        //Somebody disconnected , get his details and print 
        printf("Host disconnected unexpectedly , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port)); 

        //Close the socket and mark as 0 in list for reuse 
        closesocket(s); 
       } 
       else 
       { 
        printf("recv failed with error code : %d" , error_code); 
       } 
      } 
      if (valread == 0) 
      { 
       //Somebody disconnected , get his details and print 
       printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port)); 

       //Close the socket and mark as 0 in list for reuse 
       closesocket(s); 
      } 

      else 
      { 
     for (x = 0; buffer[x] != '\0'; x++) { 
       if (buffer[x] == AmmtA || buffer[x] == AmmtB) 
       count++; 
    } 

     char feedback[150]; 
     sprintf(feedback, "There is %d A's in your string", count); 
       feedback[MAXRECV] = '\0'; 
       printf("%s:%d - %s \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port), buffer); 
       send(s , feedback , MAXRECV , 0); 
      } 
free(buffer); 
} 

if (new_socket == INVALID_SOCKET) 
{ 
    printf("accept failed with error code : %d" , WSAGetLastError()); 
    return 1; 
} 

closesocket(s); 
WSACleanup(); 

return 0; 

}

+0

你认为查找Winsock错误代码10057? – EJP

回答

2

10057 - WSAENOTCONN - 套接字未连接。

发送呼叫是正确的,它使用new_socket。但是recv调用使用socket/sd“s”。 recv调用也应该使用new_socket。

返回错误10057,因为s只绑定到本地端点而不连接到远端,而accept返回的新套接连接到远端。

+0

谢谢你这个工作!不幸的是,现在只要客户端在服务器崩溃时输入了一些内容。 – MileJet

+0

我建议在每个阶段添加错误检查,即在每个API /系统调用之后尽可能早地捕获错误。 –

+0

这是什么意思?我对C相对比较陌生。 – MileJet

2
for (x = 0; buffer[x] != '\0'; x++) { 
      if (buffer[x] == AmmtA || buffer[x] == AmmtB) 
      count++; 
} 

你为什么比较buffer[x] 0有没有特殊原因在缓冲区内的任何特定条目应该是零,这样就可以很容易读出缓冲区的结束。也许你认为buffer包含一个字符串。但事实并非如此。它包含您从套接字读取的任何内容,并且没有特殊的格式或终结符。

幸运的是,您确实知道您读取的字节数。你存储在valread,所以你想:

for (x = 0; x < valread; x++) {