2

我有一个用 Java 编写的简单 TCP 服务器,我正在尝试为 Android 编写一个简单的 TCP 客户端,它将与本地计算机上运行的 TCP 服务器通信。

我可以让服务器接收消息,但奇怪的是它只是在我通过 Eclipse 中的“设备”窗口停止应用程序进程之后才接收消息。

在 Android 客户端上,我有一个主 UI 线程,其中包含输入 IP 地址和端口号的字段(这一切都很好,所以我不包括它的代码)。单击连接按钮时,它会启动一个新的 ASyncTask 来执行 TCP 套接字工作。

下面是 ConnectionTask 类的 doInBackground 方法的代码:

    protected Void doInBackground(Void... params) 
    {   
    String authMessage = "Authorize";
    boolean connected=false;
    try 
    {           
        Socket clientSocket = new Socket();
        SocketAddress serverAddress = new InetSocketAddress(address,port);
        Log.v("Connection Thread", serverAddress.toString());
        clientSocket.connect(serverAddress, 15);
        if(clientSocket.isConnected())
        {
            connected = true;
            Log.v("Connection Thread", "Connection Successful");
            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
            BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            outToServer.writeBytes(authMessage);
            Log.v("Connection Thread", "Sent Auth Message");
            String response = inFromServer.readLine();

            Log.v("TCP Client", "Response: " + response);
            hash = computeHash(response.getBytes());
            //send the computed hash to the server
            outToServer.writeBytes(hash);
            outToServer.close();
            inFromServer.close();
            clientSocket.close();
        }
        else
        {
            Log.v("Connection Thread", "Not Connected yet...");
        }
    } 
    catch (Exception e) 
    {
        Log.v("Connection Thread", e.getMessage());
    }   
    return null;
}

当我按下连接按钮时,在模拟器中我看到“发送身份验证消息”的日志,但我的服务器没有收到“授权”消息,直到我通过 DDMS 终止进程。

这是服务器代码:

    public class Server
{
       private static SecureRandom random = new SecureRandom();
       public static void main(String argv[]) throws Exception
       {
             String rawClientMessage,lcClientMessage;
             ServerSocket welcomeSocket = new ServerSocket(5000);
             System.out.println("Starting Server...");
             while(true)
             {
                Socket connectionSocket = welcomeSocket.accept();
                BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
                DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
                rawClientMessage = inFromClient.readLine();
                if(rawClientMessage!=null)
                {
                    lcClientMessage = rawClientMessage.toLowerCase() + '\n';
                    System.out.println("Received Message! Contents: " + rawClientMessage);
                    if(lcClientMessage=="authorize")
                    {
                        System.out.println("Received auth request message, generating key...");
                        String key = generateKey();
                        //send key back
                        outToClient.writeBytes(key);
                        System.out.println("Key sent!");
                    }
                }
                try
                {
                    inFromClient.close();
                    outToClient.close();
                    connectionSocket.close();
                }
                catch(Exception e)
                {
                    System.out.println(e.getMessage());
                }
             }
       }

       private static String generateKey()
       {
             return new BigInteger(130, random).toString(32);
       }
}

编辑:

以下是所发生情况的逐步摘要:

  1. 我启动服务器(它阻止等待连接并读取“服务器启动...”)
  2. 我在 android 客户端中输入 192.168.0.100 端口 5000 并点击“连接”按钮
  3. ASyncTask 是在单击时创建的,上面列出了我的套接字代码
  4. 服务器控制台上还没有收到任何东西......
  5. (我可以再次按下连接,什么都不会发生)(LogCat 还读取“发送验证消息”日志)
  6. 我通过 Eclipse 设备窗口杀死模拟器上的进程
  7. 服务器控制台打印:收到消息!内容:授权(如果我单击连接两次,则消息显示两次)

基本上,它似乎正在存储消息,并在程序关闭后将它们全部发送到线路上。

任何帮助表示赞赏,谢谢!可以发布更多代码,包括主 UI 线程和扩展 ASyncTask 的 ConnectionTask 类的其余部分(如果需要)。

谢谢!

4

3 回答 3

3

你在读台词,但你不是在写台词。readLine()将阻塞,直到它收到一个行终止符,并且您永远不会发送一个。readLine()而且由于您收到的数据是二进制的,因此您无论如何都不应该尝试读取它。重新考虑您的数据流。

于 2012-04-16T08:18:47.083 回答
2

writeBytes(message)将字节写入输出流,但在流被刷新之前它们不会沿管道发送。当您终止应用程序时,流将关闭,并且在流关闭之前它会自行刷新。

我想如果你在你outToClient.flush()之后添加outToClient.writeBytes(authMessage)你会摇滚的。

于 2012-04-16T06:07:27.263 回答
1

如果您在模拟器中运行您的应用程序,则必须重定向您的端口。否则你不能与服务器通信客户端。 看一看

于 2012-04-16T06:27:19.490 回答