【问题标题】:TCP Client/Server communication only sends first message?TCP客户端/服务器通信只发送第一条消息?
【发布时间】:2011-08-22 21:53:50
【问题描述】:

我正在java中设置一个简单的TCP Client Server交互。

服务器:

服务器是一个用Java编写的桌面客户端:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

class TCPServer
{
    public static int PORT_NUMBER = 6129;

    public static void main(String argv[]) throws Exception
    {
        String clientMessage;
        ServerSocket welcomeSocket = new ServerSocket(PORT_NUMBER);

        while (true)
        {
            Socket connectionSocket = welcomeSocket.accept();

            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

            clientMessage = inFromClient.readLine();

            System.out.println("Received: " + clientMessage);

            outToClient.writeBytes("I received this: "+ clientMessage +"\n");
        }
    }
}

客户:

客户端是一个安卓应用,通过 TCP 连接到服务器。在客户端,我有一个方法 sendMessage(String msg) 尝试向服务器发送消息。

public static void sendMessage(String msg) throws IOException
{
    if (mainSocket == null)
    {
        return;
    }
    if (!mainSocket.isConnected())
    {
        connectSocket();
    }
    PrintWriter output = new PrintWriter( mainSocket.getOutputStream());
    output.println(msg);
    output.flush();
    System.out.println(msg);
}

问题是,服务器收到第一条消息,但任何后续消息都不会显示。当我关闭客户端时,突然间所有其他消息都立即显示在服务器中。

这是服务器看到的:

Received: message 1

好久没活动了...
然后我关闭了客户端

Received: message 2 message 3 message 4 message 5 etc..

我在 sendMessage() 方法中放置了一个 println,并且该方法本身正在被实时调用。

【问题讨论】:

  • sendMessage 方法从什么上下文运行?是来自运行在 UI 线程上的 Activity,还是来自运行在非 UI 线程上的某个类?
  • sendMessage 是从主 UI 线程内的 Activity 中的 onKeyUp 事件调用的。这需要在自己的线程中吗?
  • 我有一个类似的问题,是由于线程错误引起的,但答案似乎是正确的;)

标签: java android tcp


【解决方案1】:

每次发送消息时,您都需要在客户端显式地close() 您的PrintWriter。当你读完 inFromClient 和写完 outToClient 后,服务器端也是如此。

另见basic example,他们很好地解释了基本工作流程:

不过,基本原理与本程序中的基本相同:

打开一个套接字。

打开一个输入流和输出流到套接字。

根据服务器的协议读取和写入流。

关闭流。

关闭套接字。

【讨论】:

  • 太棒了。我在 PrintWriter 和套接字上对 close() 进行了显式调用,它现在可以工作了。我没有意识到 close() 不会自动隐式调用。谢谢!
  • @Razor Storm 这个答案不正确。每次发送消息时都需要刷新 PrintWriter,并在对话完成后关闭它。在每条消息后关闭它会强制每条消息建立一个新连接,这非常奢侈。
  • 好的,在我的原始代码中,我在每个 sendMessage 之后都有一个flush(),并且在 printWriter 和套接字上都没有关闭,但它表现出我描述的问题。你知道这可能是什么其他原因吗?
  • 看起来你只刷新了客户端。但是您还必须在服务器端刷新。 EJP 是正确的,为每条消息重新打开一个新连接并不是最优雅的方式,但它仍然有效。您也可以尝试让连接保持打开状态,每次特定消息“完成”时在两侧刷新。
  • 似乎我的服务器的编写方式被设计为每个连接接收一条消息。我在while(connectionSocket.isConnected()){//listen for message} 的无限while 循环中放置了一个内部循环。当套接字不再连接时,它会回到监听模式。
猜你喜欢
  • 2013-04-29
  • 2019-12-06
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2023-03-08
  • 2012-04-19
  • 1970-01-01
  • 2012-10-04
相关资源
最近更新 更多