Return 消息从 java 服务器通过 tcp 套接字发送到 Android 客户端
Return message to Android client from java Server via tcp sockets
我正在尝试建立一个非常简单的 client/server 连接。我有 Android 应用程序作为客户端并尝试
1) 将消息传递给 PC 上的 Java 程序,然后
2) return 返回给 android 客户端的消息。
第一部分工作正常。问题出在 return 从服务器到客户端的消息中。
服务器代码(Java):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
private final static Integer IN_PORT = 4444;
private static ServerSocket serverSocket = null;
private static Socket sktIn;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
private static PrintWriter printWriter;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(IN_PORT); //Server socket
System.out.println("Server started. Listening to the port " + IN_PORT);
} catch (IOException e) {
System.out.println("Could not listen on port: " + IN_PORT);
}
while (true) {
try {
sktIn = serverSocket.accept(); //accept the client connection
inputStreamReader = new InputStreamReader(sktIn.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
printWriter = new PrintWriter(sktIn.getOutputStream(), true);
printWriter.write("Returned back \n"); //write the message to output stream
printWriter.flush();
printWriter.close();
inputStreamReader.close();
sktIn.close();
System.out.println(message);
} catch (IOException ex) {
System.out.println("Problem in message reading/sending.");
ex.printStackTrace();
}
}
}
}
客户端主activity (Android):
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class SimpleClientActivity extends Activity {
private final Integer OUT_PORT = 4444;
private final String S_IP = "192.168.1.104";
private EditText textField;
private Button button;
private String message;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textField = (EditText) findViewById(R.id.editText1); //reference to the text field
button = (Button) findViewById(R.id.button1); //reference to the send button
//Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
message = textField.getText().toString(); //get the text message on the text field
textField.setText(""); //Reset the text field to blank
new ConnectClient(message, S_IP, OUT_PORT, getApplicationContext()).execute();
}
});
}
}
单独的 AsyncTask class 用于连接:
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ConnectClient extends AsyncTask<String, Void, String> {
private Socket socket;
private PrintWriter printWriter;
private String param;
private Context context;
private Integer PORT;
private String IP;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public ConnectClient(String par, String ip, Integer prt, Context ctx){
super();
this.context = ctx;
this.param = par;
this.PORT = prt;
this.IP = ip;
}
@Override
public void onPreExecute() {
Toast.makeText(context, "start " + param, Toast.LENGTH_SHORT)
.show();
}
@Override
protected String doInBackground(String... params) {
try {
socket = new Socket(IP, PORT); //connect to server
printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.write(param); //write the message to output stream
printWriter.flush();
printWriter.close();
socket = new Socket(IP, PORT); // second connection to server
inputStreamReader = new InputStreamReader(socket.getInputStream());
message = "after isr";
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
inputStreamReader.close();
socket.close(); //closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return message;
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_SHORT).show()
}
@Override
protected void onProgressUpdate(Void... values) {
Toast.makeText(context, "In progress", Toast.LENGTH_SHORT).show();
}
}
java 程序执行正常,Android 应用程序运行没有任何问题,但最终结果不如预期。
如果我删除第二个 socket = new Socket(IP, PORT); // second connection to server
,则服务器可以正常接收消息。在 java 控制台中,我会打印我放入应用程序并发送的任何内容。但是第二个Toast是空的(没有传递来自服务器的消息)。我在 LogCat:
中得到 SocketException (closed)
01-29 06:38:36.039: W/System.err(11547): java.net.SocketException: Socket is closed
01-29 06:38:36.059: W/System.err(11547): at java.net.PlainSocketImpl.checkNotClosed(PlainSocketImpl.java:134)
01-29 06:38:36.059: W/System.err(11547): at java.net.PlainSocketImpl.getInputStream(PlainSocketImpl.java:216)
01-29 06:38:36.059: W/System.err(11547): at java.net.Socket.getInputStream(Socket.java:343)
01-29 06:38:36.059: W/System.err(11547): at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:63)
01-29 06:38:36.059: W/System.err(11547): at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:1)
01-29 06:38:36.059: W/System.err(11547): at android.os.AsyncTask.call(AsyncTask.java:287)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
01-29 06:38:36.059: W/System.err(11547): at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:230)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
01-29 06:38:36.059: W/System.err(11547): at java.lang.Thread.run(Thread.java:841)
如果我留下 socket = new Socket(IP, PORT); // second connection to server
行代码,则不会出现错误消息,但消息只传递到服务器一次。第二,第三,结束等等不通过(控制台中没有显示)。尽管如果我离开控制台 运行 并关闭应用程序,另一个 null 就会出现。
在任何情况下,第二个 Toast(在客户端)要么为空(来自服务器的消息未传递),要么根本不显示(message = bufferedReader.readLine();
阻止进一步执行)。例如,如果我注释掉 message = bufferedReader.readLine();
行,那么我会在第二个 Toast 中得到 "after isr"。或者,在存在第二个 socket = new Socket(IP, PORT); // second connection
的情况下,第二个 Toast 根本不显示。
我错过了什么。如何将消息从服务器发送回客户端?
客户端和服务器的指令必须是对称的。
如果客户端写入,服务器必须读取,反之亦然
如果客户端打开一个inputStream,服务器端必须打开一个outputStream。
现在在第一个连接中你只打开 outputStream 但在服务器中你同时拥有它们。
您还打开了两个在服务器中作为一个连接处理的连接(客户端),因此第一个打印操作工作正常,因为服务器上有读取操作,但其他人无法工作,因为您创建了另一个连接服务器无法处理,因为:
1)服务器不是多线程的
2) 服务器必须在第一个连接上工作
我正在尝试建立一个非常简单的 client/server 连接。我有 Android 应用程序作为客户端并尝试
1) 将消息传递给 PC 上的 Java 程序,然后
2) return 返回给 android 客户端的消息。
第一部分工作正常。问题出在 return 从服务器到客户端的消息中。
服务器代码(Java):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
private final static Integer IN_PORT = 4444;
private static ServerSocket serverSocket = null;
private static Socket sktIn;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
private static PrintWriter printWriter;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(IN_PORT); //Server socket
System.out.println("Server started. Listening to the port " + IN_PORT);
} catch (IOException e) {
System.out.println("Could not listen on port: " + IN_PORT);
}
while (true) {
try {
sktIn = serverSocket.accept(); //accept the client connection
inputStreamReader = new InputStreamReader(sktIn.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
printWriter = new PrintWriter(sktIn.getOutputStream(), true);
printWriter.write("Returned back \n"); //write the message to output stream
printWriter.flush();
printWriter.close();
inputStreamReader.close();
sktIn.close();
System.out.println(message);
} catch (IOException ex) {
System.out.println("Problem in message reading/sending.");
ex.printStackTrace();
}
}
}
}
客户端主activity (Android):
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class SimpleClientActivity extends Activity {
private final Integer OUT_PORT = 4444;
private final String S_IP = "192.168.1.104";
private EditText textField;
private Button button;
private String message;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textField = (EditText) findViewById(R.id.editText1); //reference to the text field
button = (Button) findViewById(R.id.button1); //reference to the send button
//Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
message = textField.getText().toString(); //get the text message on the text field
textField.setText(""); //Reset the text field to blank
new ConnectClient(message, S_IP, OUT_PORT, getApplicationContext()).execute();
}
});
}
}
单独的 AsyncTask class 用于连接:
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ConnectClient extends AsyncTask<String, Void, String> {
private Socket socket;
private PrintWriter printWriter;
private String param;
private Context context;
private Integer PORT;
private String IP;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public ConnectClient(String par, String ip, Integer prt, Context ctx){
super();
this.context = ctx;
this.param = par;
this.PORT = prt;
this.IP = ip;
}
@Override
public void onPreExecute() {
Toast.makeText(context, "start " + param, Toast.LENGTH_SHORT)
.show();
}
@Override
protected String doInBackground(String... params) {
try {
socket = new Socket(IP, PORT); //connect to server
printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.write(param); //write the message to output stream
printWriter.flush();
printWriter.close();
socket = new Socket(IP, PORT); // second connection to server
inputStreamReader = new InputStreamReader(socket.getInputStream());
message = "after isr";
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
inputStreamReader.close();
socket.close(); //closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return message;
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_SHORT).show()
}
@Override
protected void onProgressUpdate(Void... values) {
Toast.makeText(context, "In progress", Toast.LENGTH_SHORT).show();
}
}
java 程序执行正常,Android 应用程序运行没有任何问题,但最终结果不如预期。
如果我删除第二个 socket = new Socket(IP, PORT); // second connection to server
,则服务器可以正常接收消息。在 java 控制台中,我会打印我放入应用程序并发送的任何内容。但是第二个Toast是空的(没有传递来自服务器的消息)。我在 LogCat:
01-29 06:38:36.039: W/System.err(11547): java.net.SocketException: Socket is closed
01-29 06:38:36.059: W/System.err(11547): at java.net.PlainSocketImpl.checkNotClosed(PlainSocketImpl.java:134)
01-29 06:38:36.059: W/System.err(11547): at java.net.PlainSocketImpl.getInputStream(PlainSocketImpl.java:216)
01-29 06:38:36.059: W/System.err(11547): at java.net.Socket.getInputStream(Socket.java:343)
01-29 06:38:36.059: W/System.err(11547): at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:63)
01-29 06:38:36.059: W/System.err(11547): at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:1)
01-29 06:38:36.059: W/System.err(11547): at android.os.AsyncTask.call(AsyncTask.java:287)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
01-29 06:38:36.059: W/System.err(11547): at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:230)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
01-29 06:38:36.059: W/System.err(11547): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
01-29 06:38:36.059: W/System.err(11547): at java.lang.Thread.run(Thread.java:841)
如果我留下 socket = new Socket(IP, PORT); // second connection to server
行代码,则不会出现错误消息,但消息只传递到服务器一次。第二,第三,结束等等不通过(控制台中没有显示)。尽管如果我离开控制台 运行 并关闭应用程序,另一个 null 就会出现。
在任何情况下,第二个 Toast(在客户端)要么为空(来自服务器的消息未传递),要么根本不显示(message = bufferedReader.readLine();
阻止进一步执行)。例如,如果我注释掉 message = bufferedReader.readLine();
行,那么我会在第二个 Toast 中得到 "after isr"。或者,在存在第二个 socket = new Socket(IP, PORT); // second connection
的情况下,第二个 Toast 根本不显示。
我错过了什么。如何将消息从服务器发送回客户端?
客户端和服务器的指令必须是对称的。
如果客户端写入,服务器必须读取,反之亦然
如果客户端打开一个inputStream,服务器端必须打开一个outputStream。
现在在第一个连接中你只打开 outputStream 但在服务器中你同时拥有它们。
您还打开了两个在服务器中作为一个连接处理的连接(客户端),因此第一个打印操作工作正常,因为服务器上有读取操作,但其他人无法工作,因为您创建了另一个连接服务器无法处理,因为:
1)服务器不是多线程的
2) 服务器必须在第一个连接上工作