如何让Android客户端监听C#服务器?

8
我可以帮助您进行翻译。以下是需要翻译的内容:

我有一个Android客户端和一个C#服务器。客户端向服务器发送消息,一切正常。但我需要服务器在请求时发送指定目录中文件夹和文件列表,但不知道如何做到这一点,因为客户端没有收到来自服务器的任何消息。客户端用于监听的代码部分不起作用,应用程序会一直卡住,直到我关闭服务器应用程序,然后它才能正常工作,但仍然无法读取任何内容。 提前感谢。

客户端:

package com.app.client.app;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStream;
import java.io.OutputStreamWriter; 
import java.io.InputStreamReader;
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 

import android.util.Log; 

public class my_activity extends Activity { 
private TextView txt;

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    Button b = (Button)findViewById(R.id.button1);
    txt = (TextView)findViewById(R.id.textView1);


    b.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        connectSocket("Hello");

        }
    });
} 

private void connectSocket(String a){ 

    try { 
        InetAddress serverAddr = InetAddress.getByName("192.168.1.2"); 
        Log.d("TCP", "C: Connecting..."); 
        Socket socket = new Socket(serverAddr, 4444); 

        message = "1";

        PrintWriter out = null;
        BufferedReader in = null;

        try { 
            Log.d("TCP", "C: Sending: '" + message + "'"); 
            out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); 
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));                

            out.println(message);
            while ((in.readLine()) != null) {
                txt.append(in.readLine());
            }

            Log.d("TCP", "C: Sent."); 
            Log.d("TCP", "C: Done.");               

        } catch(Exception e) { 
            Log.e("TCP", "S: Error", e); 
        } finally { 
            socket.close(); 
        } 

    } catch (UnknownHostException e) { 
        // TODO Auto-generated catch block 
        Log.e("TCP", "C: UnknownHostException", e); 
        e.printStackTrace(); 
    } catch (IOException e) { 
        // TODO Auto-generated catch block 
        Log.e("TCP", "C: IOException", e); 
        e.printStackTrace(); 
    }       
} 
} 

服务器:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;

public class serv {
    public static void Main() {
    try {
    IPAddress ipAd = IPAddress.Parse("192.168.1.2");
     // use local m/c IP address, and 

     // use the same in the client


/* Initializes the Listener */
    TcpListener myList=new TcpListener(ipAd,4444);

/* Start Listeneting at the specified port */        
    myList.Start();

    Console.WriteLine("The server is running at port 4444...");    
    Console.WriteLine("The local End point is  :" + 
                      myList.LocalEndpoint );
    Console.WriteLine("Waiting for a connection.....");
    m:
    Socket s=myList.AcceptSocket();
    Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);

    byte[] b=new byte[100];
    int k=s.Receive(b);

    char cc = ' ';
    string test = null;
    Console.WriteLine("Recieved...");
    for (int i = 0; i < k-1; i++)
    {
        Console.Write(Convert.ToChar(b[i]));
        cc = Convert.ToChar(b[i]);
        test += cc.ToString();
    }

    switch (test)
    {
        case "1":                 
            break;


    }

    ASCIIEncoding asen=new ASCIIEncoding();
    s.Send(asen.GetBytes("The string was recieved by the server."));
    Console.WriteLine("\nSent Acknowledgement");


/* clean up */
    goto m;    
    s.Close();
    myList.Stop();
    Console.ReadLine();

}
catch (Exception e) {
    Console.WriteLine("Error..... " + e.StackTrace);
}    
}

}

Console.WriteLine("Recieved..."); 会被打印出来吗? - Haphazard
1
只是好奇为什么您没有选择使用SOAP方法,是因为性能问题吗? - Allen Rice
@Allen 我没有想到 SOAP,只是找了一些教程然后跟着做。 - 3Gee
@3Gee 请问 Log.d("TCP", "C: Sent.");Console.WriteLine("\nSent Acknowledgement"); 是否已经被发送了?它们在哪里停止写入? - Haphazard
@Haphazard 我认为 Console.WriteLine("\nSent Acknowledgement"); 和 Log.d("TCP", "C: Sent."); 都不应该被发送,因为我在手机屏幕上点击一个按钮后,它会一直停留在“按下”状态,直到我关闭服务器应用程序。 - 3Gee
显示剩余4条评论
3个回答

6

好的,我找到了解决您问题的方法。

在您发送文本的C#服务器中:

ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
s.Close();

在发送数据后,请确保在此处关闭套接字。这就是为什么您的应用程序会挂起。它正在等待来自服务器的更多输入。

另外,在Java中接收时,请改为以下方式

String text = "";
String finalText = "";
while ((text = in.readLine()) != null) {
    finalText += text;
    }
txt.setText(finalText);

注意在循环中你进行了两次readInputs操作。while语句执行了一次,而设置文本也执行了一次,因此你实际上是在一个循环中尝试读取两行。改成我上面发布的内容就可以解决这个问题。

我已经将你的代码复制粘贴到一个项目中,并且完全按照我的要求进行了复制和粘贴,每次都能完美地运行。 - dymmeh
text += URLDecoder.decode(input, "UTF-8"); <--这行代码比仅使用"finalText += text;"更好,因为后者的结果文本中有"+"号而不是空格。 - 3Gee
@dymmeh,你能告诉我为什么你改变了之前评论中提到的那些行吗?因为我真的不明白。 - 3Gee
我最初把它们放在那里是因为这是我在我的应用程序中的做法。然而,后来我进行了无需它们的测试,发现它们并不需要才能工作。我认为添加额外的代码并不能帮助解决问题,所以我将其删除了。如果我让你感到困惑,对此我很抱歉! - dymmeh

4
为避免NetworkOnMainThreadException,您需要在新线程中执行通信代码。
在Android客户端中:
 @Override
 public void onClick(View v) {

 new Thread(new Runnable() {
        public void run() {
            connectSocket("Hello");
                }
        }).start();

 }

3
感谢您提供的代码示例!
仅供参考:
您需要设置以下权限:
    <uses-permission android:name="android.permission.INTERNET" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接