2010-10-27 270 views
1

我正在將我的代碼粘貼到C和Java客戶端中的簡單套接字服務器上。C套接字服務器,Java套接字客戶端:阻塞!

我使用寫入方法在Java中逐字發送。然而,在發送大塊字符(在這裏,'h','e','y')後,Java客戶端被髮送阻塞,因爲C服務器不回覆它:(

我假設有一些問題,發送一個空字符(從Java寫),將在C面停止的recv

任何幫助,將不勝感激

C服務器:。

#include <stdio.h> /* standard in and output*/ 
#include <sys/socket.h> /* for socket() and socket functions*/ 
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */ 
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  /* for close() */ 


int main(int argc, char *argv[]){ 
int sock, connected, bytes_received, true = 1; 
    char recv_data;  
char replyBuffer[32]; 

    struct sockaddr_in server_addr,client_addr;  
    int sin_size;  
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
     perror("Socket"); 
     exit(1); 
    } 

    if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) { 
     perror("Setsockopt"); 
     exit(1); 
    } 

    server_addr.sin_family = AF_INET;   
    server_addr.sin_port = htons(2400);  
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    bzero(&(server_addr.sin_zero),8); 

    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { 
     perror("Unable to bind"); 
      exit(1); 
    } 

    if (listen(sock, 5) == -1) { 
     perror("Listen"); 
     exit(1); 
    } 

printf("\nTCPServer Waiting for client on port 2400"); 

    while(1){ 
     sin_size = sizeof(client_addr); 
     connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); 
     printf("\n Got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); 


     while ((bytes_received = recv(connected,&recv_data,1,0)) > 0){ 
    printf("\nrecv= %c\n", recv_data); 
    } 
    int success = 1; 
    sprintf(replyBuffer, "%d", success); 
    printf("reply buffer = %s\n", replyBuffer); 
    if (send(connected, replyBuffer, strlen(replyBuffer), 0) == -1) 
    perror("send() failed"); 
    success = 0; 
    close(connected); 
} 
} 

Java客戶端:

import java.net.*; 
import java.io.*; 

public class Client1 
{ 
public static void main(String[] args) throws IOException { 
    if (args.length < 2) { 
    System.err.println("Usage: java Client1 <IP address> <Port number>"); 
    System.exit(0); 
    } 
    BufferedReader in = null; 
    OutputStream out = null; 
    Socket sock = null; 

    try { 
    sock = new Socket(args[0], Integer.parseInt(args[1])); 
    out = sock.getOutputStream(); 
    in = new BufferedReader(new InputStreamReader(sock.getInputStream())); 

    String line = "hey"; 
    String responseline = null; 
char[] strArray; 
strArray = line.toCharArray(); 

while (true) { 
for(int index = 0; index < strArray.length; index++){ 
out.write(strArray[index]); 
} 
out.flush(); 
System.out.println("data sent "); 
System.out.println("val returned"+in.readLine()); 
    } 
    } 
    catch (IOException ioe) { 
    System.err.println(ioe); 
    } 
    finally { 
    if (in != null) 
    in.close(); 

    if (out != null) 
    out.close(); 
    if (sock != null) 
    sock.close(); 
    } 
} 
} 
+0

@ user489152:你應該接受一個答案。 – andersoj 2010-11-02 14:10:57

回答

8

從Javadoc文檔BufferedReader.readLine()

Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed. 

這就是爲什麼它塊(不LF,沒有CR,沒有CRLF)

[編輯]
你需要創建一個EOL指示C程序可以理解(就像在java客戶端中的readLine()一樣)。讓該指標爲'\ n'(爲了一致性,如果沒有其他)
在Client.java中,將'\ n'附加到您發送的字符串。
在tst.c,測試 '\ n',它在接收時,突破來自的recv()循環
[/編輯]

+0

但是我試着發送'/ n','/ 0','/ r',這些都沒有工作......最後我甚至嘗試傳遞'null',然後服務器響應,但是立即,我的java客戶端停止了可以理解的在零點異常之後。 – user489152 2010-10-28 06:16:08

+0

謝謝凱文,我做了這些,現在C代碼進一步發展,在它接收到整個字符集之後,它返回一個值(replyBuffer中success = 1),但是這次java代碼塊中的in.readLine() !但它不承認空字符?我甚至把in.readLine()放在while循環中,直到它不等於null ...但它會阻止...:(:( – user489152 2010-10-28 16:24:56

+0

在兩個方向的通信必須'\ n'終止(這是你的EOL指標在兩邊) - sprintf(replyBuffer,「%d \ n」,成功); – KevinDTimm 2010-10-28 16:36:47

2

你的問題的假設是正確的。調用recv將始終返回大於零的值。我建議使用特殊字符指定文本的結尾,並在讀取該字符時終止recv()循環。

+0

但我試着發送'/ n','/ 0','/ r',這些都沒有工作...最後我甚至嘗試過傳遞'空',然後服務器響應,但立即,我的Java客戶端停止空點異常後可以理解。 – user489152 2010-10-28 06:14:48

+0

史蒂夫,你能提出一些特殊的特徵嗎?順便說一句,我會用這個程序來傳遞ASCII文件(文本)...任何建議? – user489152 2010-10-28 06:15:44

+0

一旦EOL終結符被定義,發送和識別,這一切都很好:) – KevinDTimm 2010-10-28 12:21:50

0

在我看來,你的服務器代碼有錯誤。如果你在linux上編譯你的服務器代碼,會出現錯誤。 sin_size的類型應該是socklen_t。 或者你會看到一個錯誤信息 「從int *無效的轉換爲socklen_t」

0

客戶改變

out.write(line.getBytes()); 

服務器更改爲

char recv_data[32]; 
recv(connect,recv_data,32,0);