奇怪行为

问题描述:

我的服务器 - 客户端应用程序包含以下模块:奇怪行为

客户端(用Java编写的)连接到服务器并发送的文件;

服务器(用C写)接收文件并发送字符数组消息。

问题是,收到文件后,服​​务器无法发送消息或客户端无法接收它。

这里是我的服务器应用程序的代码:

int main(int argc , char *argv[]) 
{ 
    WSADATA wsa; 
    SOCKET s , new_socket; 
    struct sockaddr_in server , client; 
    int c, bytecount, nr_transf, rest_byte, i, bytesRead; 
    int recv_size, file_size; 
    char message[1000];  
    char buffer[1000]; 
    int buffer_len = 1000; 
    FILE *f = fopen("out.jpg", "wb"); 

    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()); 
     getch(); 
     return 0; 
    } 

    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(8888); 

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

    puts("Bind done"); 

    //Listen to incoming connections 
    listen(s, 3); 

    //Accept and incoming connection 
    printf("Waiting for incoming connections..."); 

    c = sizeof(struct sockaddr_in); 
    new_socket = accept(s, (struct sockaddr*)&client, &c); 
    if (new_socket == INVALID_SOCKET) 
    { 
     printf("accept failed with error code : %d", WSAGetLastError()); 
     getch(); 
     return 0; 
    } 

    printf("Connection accepted"); 

    //Receive image 
    while((bytesRead = recv(new_socket, buffer, buffer_len, 0)) > 0) 
    { 
     fwrite(buffer, 1, bytesRead, f); 
    } 

    fclose(f); 
    printf("\nReceive finished!"); 


    //Send messsage 
    char my_message[100]; 
    strcpy(my_message, "Hello World!"); 

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

    closesocket(s); 
    WSACleanup(); 

    getch(); 
    return 0; 
} 

而对于客户端应用程序的代码:

public class MyClass 
{ 
    public static void main(String[] args) 
    { 
     String fileName = "1.jpg", receiveMessage; 
     File a_file = new File(fileName); 
     int j; 
     OutputStream output = null; 
     InputStream input = null; 
     ObjectInputStream in = null; 
     Socket socket = null; 

     try 
     {   
      // Create a socket 
      socket = new Socket("192.168.0.122", 8888); 

      FileInputStream fileInputStream = new FileInputStream(fileName); 
      byte[] buffer = new byte[1000]; 
      int bytesRead = 0; 
      output = socket.getOutputStream();  
      input = socket.getInputStream();  

      while((bytesRead = fileInputStream.read(buffer))>0) 
      { 
       output.write(buffer,0,bytesRead); 
      } 

      fileInputStream.close();   
      System.out.println("Send finished!"); 

      input.read(buffer); 
      System.out.println("Receive finished!"); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
     finally 
     { 
      try 
      { 
       in.close(); 
       output.close(); 
       socket.close(); 
      } 
      catch(Exception e) 
      { 

      } 
     } 
    } 
} 

任何想法来解决这个问题?提前致谢!

+0

你的程序中有痕迹。这两个程序在会话期间的输出是什么? – Offirmo

+0

那么,在图像发送后,两个程序都会锁定... – adrian2012

这是因为你有阻塞插座。当一个套接字被创建时(通过连接或接受)它处于阻塞模式。这意味着如果没有数据接收它将不会返回,从而有效地阻止了调用者。

因此,在收到服务器循环中的最后一个字节后,recv调用将无限期阻止。

在带winsocket的Windows上,您可以使用ioctlsocket函数使套接字成为阻塞或非阻塞。链接的引用有一个例子,它显示了热插拔阻塞或非阻塞。

+2

+1 - 除非OP更改协议,否则服务器无法知道所有文件数据都已收到。 –