2013-04-18 95 views
0

我的服務器 - 客戶端應用程序包含以下模塊:奇怪行爲

客戶端(用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

回答

3

這是因爲你有阻塞插座。當一個套接字被創建時(通過連接或接受)它處於阻塞模式。這意味着如果沒有數據接收它將不會返回,從而有效地阻止了調用者。

因此,在收到服務器循環中的最後一個字節後,recv調用將無限期阻止。

在帶winsocket的Windows上,您可以使用ioctlsocket函數使套接字成爲阻塞或非阻塞。鏈接的引用有一個例子,它顯示了熱插拔阻塞或非阻塞。

+2

+1 - 除非OP更改協議,否則服務器無法知道所有文件數據都已收到。 –