已解决:我在第一次连接后没有重新启动服务器。现在它的工作非常漂亮;)
我在Android设备和PC之间遇到TCP连接问题。在PC上我有tcp服务器与ServerSocket等待接受,并且本地网络中的Android设备试图连接到它。当我将静态IP地址放到代码中时,一切都很好,但是当我以编程方式(在硬编码端口上从0到255搜索192.168.1.x)时,它接受连接,但我无法从ServerSocket接收数据,也无法接收数据来自Android套接字。
在Android上我有3个按钮的Widget,所有通信都由AsyncTasks处理。这是TCP服务器:
public class TCPClient {
private static final String TAG = "TCPClient";
private final Handler mHandler;
private String ipNumber;
BufferedReader in;
PrintWriter out;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private String serverMessage,command;
public TCPClient(Handler mHandler, String command, String ipNumber, OnMessageReceived listener) {
mMessageListener = listener;
this.ipNumber = ipNumber;
this.command = command;
this.mHandler = mHandler;
}
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
mHandler.obtainMessage(MainActivity.SENDING);
Log.d(TAG, "Sent Message: " + message);
}
}
public void stopClient(){
mRun = false;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(ipNumber);
Log.d(TAG, "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, 4444);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.d("TCP Client", "C: Sent.");
Log.d("TCP Client", "C: Done.");
//receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.sendMessage(command);
//in this while the client listens for the messages sent by the server
while (mRun) {
serverMessage = in.readLine();
Log.d("TCP", "S: Received Message: '" + serverMessage + "'");
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.d("TCP", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) {
Log.d("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
out.flush();
out.close();
in.close();
socket.close();
Log.d("TCP", "Socket Closed");
}
} catch (Exception e) {
Log.d("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
这里我有AsyncTask来启动和处理连接:
public class ShutdownAsyncTask extends AsyncTask<String, String, TCPClient> {
private static final String COMMAND = "shutdown -s";
private TCPClient tcpClient;
private Handler mHandler;
private static final String TAG = "ShutdownAsyncTask";
public ShutdownAsyncTask(Handler mHandler){
this.mHandler = mHandler;
}
@Override
protected TCPClient doInBackground(String... params) {
Log.d(TAG, "In do in background");
try{
tcpClient = new TCPClient(mHandler,COMMAND, new IpGetter().getIp(), new TCPClient.OnMessageReceived() {
@Override
public void messageReceived(String message) {
publishProgress(message);
}
});
}catch (NullPointerException e){
Log.d(TAG, "Caught null pointer exception");
e.printStackTrace();
}
tcpClient.run();
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d(TAG, "In progress update, values: " + values);
if(values.equals("connected")){
tcpClient.sendMessage(COMMAND);
tcpClient.stopClient();
mHandler.obtainMessage(MainActivity.SHUTDOWN);
}else{
tcpClient.sendMessage("wrong");
mHandler.obtainMessage(MainActivity.ERROR);
tcpClient.stopClient();
}
}
@Override
protected void onPostExecute(TCPClient result){
super.onPostExecute(result);
Log.d(TAG, "In on post execute");
}
}
这里我有IpGetter类,它有方法getIp(),用于动态地从本地网络获取IP:
public class IpGetter {
private static Future<String> portIsOpen(final ExecutorService es, final String ip, final int port, final int timeout) {
Log.d("IpGetter", "In portIsOpen");
return es.submit(new Callable<String>() {
@Override public String call() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
Log.d("portIsOpen", "ip: " + ip);
return ip;
} catch (Exception ex) {
return null;
}
}
});
}
public static String getIp(){
final ExecutorService es = Executors.newFixedThreadPool(20);
final int timeout = 200;
final int port = 4444;
final List<Future<String>> futures = new ArrayList<Future<String>>();
for (int i = 0; i <= 255; i++) {
String ip = "192.168.1."+i;
futures.add(portIsOpen(es, ip, port, timeout));
}
es.shutdown();
for (final Future<String> f : futures) {
try {
if (f.get() != null) {
Log.d("F get", f.get());
return f.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return null;
}
}
在服务器端,一切正常。当我改变时,一切都在变化:
try{
tcpClient = new TCPClient(mHandler,COMMAND, "192.168.1.103",...
要:
try{
tcpClient = new TCPClient(mHandler,COMMAND, new IpGetter().getIp(),....
有谁知道如何管理它?谢谢你的帮助。
答案 0 :(得分:0)
好的,我解决了。事实证明,在打开IpGetter的套接字后,我没有重启服务器。现在我已经完成了!