【发布时间】:2016-07-26 06:39:20
【问题描述】:
在我的项目中,有一个服务器为客户服务并为他们服务。
服务器----主
ss = new ServerSocket(12345);
System.out.println("Server started..");
while(true)
{
System.out.println("Waiting For clients...");
Socket client = ss.accept();
System.out.println("Got client...");
Thread t = new Thread(new Handler(client));
t.start();
//exe.execute(new Handler(client));
}
这是在 main 方法中,服务器创建一个无限循环(线程)来接受传入的连接。一旦接收到连接,服务器将创建一个新的 Handler 对象,该对象将已连接的客户端作为参数。
处理程序类
public class Handler implements Runnable {
Socket client;
public Handler(Socket client) {
// TODO Auto-generated method stub
this.client = client;
}
@Override
public void run() {
// TODO Auto-generated method stub
//streams
try {
OutputStream out = client.getOutputStream();
PrintWriter writer = new PrintWriter(out);
InputStream in = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String s = null;
while((s=reader.readLine())!=null)
{
//will switch on string or convert to json object
System.out.println("Recieved: " + s);
}
writer.close();
reader.close();
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
在这个类中,主要目标是处理客户的请求。所以构造函数将套接字对象初始化为它拥有的实例。
在 run 方法中,对象被实例化,然后有一个无限循环,假设打印来自客户端的任何传入消息。
当客户端断开连接时循环会中断,这就是close()
方法被调用,优雅地关闭和释放资源。至此,线程结束。
客户端 - (Android)
public class MainActivity extends AppCompatActivity {
final String ip = "192.168.0.18";
final int port = 12345;
Socket client;
OutputStream out;
PrintWriter writer;
InputStream in;
BufferedReader reader;
final String TAG = "Debug: ";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new ConnectToServer().execute();
new SendToServer().execute();
}
class ConnectToServer extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params)
{
try {
client = new Socket(ip,port);
//Log.d(TAG, "doInBackground: connected to server");
//set streams
out = client.getOutputStream();
writer = new PrintWriter(out);
in = client.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
Log.d(TAG, "doInBackground: Sent");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
class SendToServer extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params) {
writer.write("lol");
writer.flush();
return null;
}
}
}
我上一次使用 Android Studio 是在一年左右之前,我非常肯定网络/IO 操作可以在主线程上运行。但是黄金法则意味着不阻塞主线程,并且有一些阻塞方法。
我选择使用AsyncTask 接口,因为它封装了较低级别的Thread 类(对我来说更易于使用/了解生命周期)。
ConnectToServer类成功连接到服务器,但是一旦调用SendToServer类,服务器就收不到消息了。
一旦我断开客户端(终止应用程序),服务器就会打印出消息。
为什么客户端断开后服务器才收到消息?
【问题讨论】:
-
为什么有两个异步任务?
-
@Pooya 据我了解,我没有关闭连接。当 Android 客户端终止应用程序时,连接将关闭。当应用程序关闭时,它将向服务器返回 0 或 -1,而 BufferedReader 对象将读取此值并跳出循环,然后关闭流和套接字。
-
@Pooya 一个AsyncTask用于连接服务器,另一个AsynTask用于向服务器发送数据。
-
只是一个疯狂的猜测,但值得一试:将“writer”值更改为:writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
-
@Pooya 不起作用,通过此修改,服务器在客户端连接时不会收到消息。当客户端断开连接时,服务器会收到消息。
标签: java android multithreading sockets android-asynctask