【问题标题】:Communication between Client and Server using Sockets客户端和服务器之间使用套接字进行通信
【发布时间】:2011-04-16 21:14:41
【问题描述】:

好的,这是今天早些时候修改过的问题,我已经包含代码来帮助解释问题。我正在从客户端向服务器发送两条消息。然后服务器拾取消息并处理它们。服务器最终尝试将消息发送回客户端(请在服务器代码“testmessage”中注明),这是我遇到问题的地方。要么是我没有在客户端收到消息,要么是从服务器端错误地发送了消息。

public class ClientConnection {

String address, language, message;
int portNumber;
Socket clientSocket = null;

public ClientConnection(String lan, String mes, String add, int pn) throws IOException{
    address = add;
    portNumber = pn;
    language = lan;
    message = mes;
}
public String createAndSend() throws IOException{
    // Create and connect the socket
    Socket clientSocket = null;
    clientSocket = new Socket(address, portNumber);
    PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(),true);
    BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));     

    // Send first message - Message is being correctly received
    pw.write(language+"\n"); 
    pw.flush(); 
    // Send off the data  

    // Send the second message - Message is being correctly received
    pw.write(message); 
    pw.flush();
    pw.close();
    // Send off the data

    // NOTE: Either I am not receiving the message correctly or I am not sending it from the server properly.
    String translatedMessage = br.readLine();       
    br.close();
    //Log.d("application_name",translatedMessage); Trying to check the contents begin returned from the server.
    return translatedMessage;
}

服务器代码:

public class ServerConnection {

public static void main(String[] args) throws Exception {       
    // Delete - Using while loop to keep connection open permanently.
    boolean status = false;
    while( !status){
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 4444.");
            System.exit(1);
        }
        Socket clientSocket = null;
        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }
        // Delete - Working as of here, connection is established and program runs awaiting connection on 4444
        BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));     
        String language = br.readLine();
        String message = br.readLine();
        // Test - Works
        System.out.println(language);      
        // Test - Works
        System.out.println(message);
        // Delete - Working as of here, both messages are passed and applied. Messages are received as sent from client.
        TranslateMessage tm = new TranslateMessage();
        String translatedMessage = tm.translateMessage(language, message);

        // NOTE: This seems to be where I am going wrong, either I am not sending the message correctly or I am not receiving it correctly..
        // PrintWriter writer = new PrintWriter(new BufferedOutputStream(clientSocket.getOutputStream()));
        PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(),true);
        // Send translation back 
        System.out.println(translatedMessage);
        // pw.write(translatedMessage+"\n"); 
        pw.write("Return test"); // Test message!
        pw.flush(); 
        // Send off the data 
        pw.close();
        br.close();
        clientSocket.close();
        serverSocket.close();
    }
}
}

代码有点乱,我可以看到一些重复,我已经评论了我觉得问题发生的地方。

感谢您的帮助!

【问题讨论】:

  • 客户端的readline返回什么?是空的吗?
  • 不是一个字符串,虽然在这个例子中它应该是从服务器发送的“字符串测试”。
  • 我仍然会在 pw.write("Return test\n") 上添加一个 \n 来消除它作为一个问题。
  • 我做了 Jim 但仍然无济于事。也许新的一天会产生更好的结果。

标签: java android sockets


【解决方案1】:

您正在使用 BufferedReader.readLine() 从服务器读取响应,但在测试用例中,您发送的字符串不是以 \n 或 \r\n 结尾的,因此它不会得到该行据我从文档中得知...

public String readLine()
            throws IOException

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.

Returns:
    A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached

另外的建议...

在编写这样的请求响应协议时,我不会依赖行尾来终止请求或响应。通常我会使用完全格式化的 JSON 字符串,或者我的偏好是二进制协议,其中所有请求和响应都以二进制计数(通常为 4 字节 bigendian/网络字节顺序)开头。然后客户端和服务器读取 4 个字节,然后读取后面的字节数。这可以处理通常在网络连接上发生的数据包碎片,还有助于避免恶意用户发送永不终止的长字符串进行 DOS 攻击。

在 Java 中,您可以使用 ByteBuffer.order() 来处理 bigendian 数。

【讨论】:

  • 嗨,吉姆,感谢您的评论,如果您看上面的内容,我正在使用发送带有 \n 的变量,但它也不起作用。
  • 哦,我看到您在客户端执行 readline 之前关闭了打印机,这可能不太好,因为它们使用的是同一个套接字。
  • 我尝试移动 pw.close 并且我运行的 android 应用程序冻结了。嗯
  • 您是否在发送的测试字符串中添加了\n,它将冻结等待读取整个字符串直到\n。
  • 如果你只是关闭套接字,我认为没有必要关闭 printwriter 或 bufferedreader,我认为它们也会被关闭。
猜你喜欢
  • 2013-06-24
  • 2013-05-14
  • 2012-04-21
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 2016-02-07
相关资源
最近更新 更多