设置Socket Client一直监听数据
Set up Socket Client always listen data
我可以设置客户端Socket
向服务器发送请求(sendData()
方法)并正确读取接收到的消息(readData()
方法),但我每次都只收到消息我通过以下代码使用 MOBILE_REQUEST
字符串向服务器发送请求:
@Override
protected Boolean doInBackground(String... params) {
try {
mSocket = new Socket(
// PC Ip is 192.168.1.199
// It is the other device, Not be local host : 127.0.0.1
Pas.pas.getPcIP(), 17001);
DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());
String RESPONSE = null;
String MOBILE_BLOCK = "MobileBlock#";
// Converting collected data in byte array into String.
RESPONSE = sendData(mDos, MOBILE_BLOCK);
/**
* The result response from PC app in here
*/
// Log : response - #WindowsResp#192.168.1.199#
Log.i("", "response '" + RESPONSE + "'");
}
} catch (SocketTimeoutException e) {
IS_SOCKET_TIME_OUT = true;
e.printStackTrace();
} catch (ConnectException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
sendData()
方法 - 客户端向服务器发送请求并等待获取响应数据 - 字符串数据。
private String sendData(DataOutputStream mDos, String MOBILE_REQUEST) {
try {
// Log : MOBILE_REQUEST.getBytes() - [B@82f10f8
mDos.write(MOBILE_REQUEST.getBytes());
// todo I should set this sleep, bcs TCP has delay time,
// so i need set the delay time for client should receive data
// otherwise, sometimes I did not receive anything
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Log : #WindowsResp#192.168.1.199#
return new String(readData(mSocket));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
readData()
方法 - 从服务器接收后读取数据。
public static byte[] readData(Socket mSocket) {
/* Since data are accepted as byte, all of them will be collected in the
following byte array which initialised with accepted data length. */
DataInputStream mDis = null;
try {
mDis = new DataInputStream(mSocket.getInputStream());
// Log : mDis.available() - 23
byte[] data = new byte[mDis.available()];
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
// Log : data - [B@30c044a4
return data;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
我想要的是每次服务器通过单击按钮向我的套接字客户端发送消息时,套接字客户端应该接收它。但在上面的代码中,它不是。
请帮助我如何设置套接字客户端总是从服务器监听?
p/s : 或者我需要设置 ServerSocket
?如果使用 ServerSocket
我不能使用相同的端口,对吗?因为当我首先打开 ServerSocket
进行监听时(例如在端口 17001),我无法使用客户端套接字通过端口 17001 发送请求,因为该端口已被使用。
已更新
服务器(PC 应用程序 - 笔记本电脑设备)发送到客户端(移动设备 - Android)的方式是通过 Socket TCP,通过以下步骤:
1 - 客户端(Android 设备)建立到服务器(PC 应用程序)的 TCP 套接字连接(此连接永远不会关闭,直到在 onDestroy()
方法中退出应用程序)。
2 - 客户端向服务器发送请求,例如。 MOBILE_REQUEST = "MobileID#MobileIP#"
3 - 服务器收到客户端的请求,通过Socket连接回复客户端,实际上客户端正确接收到数据。前任。 "WindowsRep#WindowsIP"
这种方式对我不起作用,即使 socket TCP 连接没有关闭,getInputStream()
也没有关闭。在这种情况下:
服务器通过Socket连接向客户端发送字符串数据,客户端正确接收到数据。
我想要的是每一次"Server send string data to client via Socket connection, client received data correctly"。但就我而言,客户端仅在向服务器发送请求后才接收数据。
C# 服务器
服务器套接字
IPEndPoint ipe = new IPEndPoint("192.168.1.199", 17001);
svSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
svSocket.Bind(ipe);
服务器发送数据
string data_send = "#WBroad#" + "192.168.1.199" + "#";
byte[] byteData = Encoding.UTF8.GetBytes(data_send);
c.ClientSocket.Send(byteData);
由于您还没有 posted 发送代码,因此无法说出您为什么没有收到数据,但这里是对您所拥有内容的快速评论 posted:
// mSocket.setReuseAddress(true);
您已将其注释掉,但现在调用此方法将毫无意义。您必须将套接字构造为 new Socket()
,不带参数,然后调用此方法,然后调用 connect()
。由于您没有提供要重复使用的源端口或 IP 地址,因此它仍然毫无意义。
byte[] data = new byte[mDis.available()];
这完全是对 available()
的误用。它不提供消息长度。请参阅Javadoc。没有理由相信此时到达的任何数据,如果有,是一条完整的消息,或者只是一条消息。如果您需要消息,您将无法从 TCP 获得任何帮助:您必须自己实现它们。由于您的协议似乎是基于文本的,我建议您只使用行和 readLine()
,以及 BufferedReader
和 BufferedWriter
而不是 DataInput/OutputStreams
。并在套接字的生命周期内构造一次,而不是每个应用程序消息构造一次,否则您将丢失数据。
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
这个巨大的问题是它不会阻塞,因为大多数时候,available()
将为零,所以这个方法什么都不做除了 return 一个空的 byte[]
数组。
在任何情况下,这都完全等同于 mDis.readFully(data);
,只是效率低了数倍,但无论如何你都不应该这样做:见上文。
return data;
} catch (IOException e) {
e.printStackTrace();
}
return null;
这是不好的做法。你应该让IOException
被这个方法抛出,让调用者处理它。
mDos.write(MOBILE_REQUEST.getBytes());
见上文。这应该包括一个行终止符、一个长度字前缀或一些其他的消息定界方式。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
这种睡眠完全是浪费时间。和 space。去掉它。睡在网络代码中只是货物崇拜编程。
return new String(readData(mSocket));
这将抛出 NullPointerException
if readData()
returns null
,如果存在 IOException
,它会抛出 NullPointerException
,这是另一个原因让该方法传播该异常,而不是在内部捕获它并 returning null.
private boolean splitData(int mobile_send_request_case, String DATA) {
此方法与问题完全无关,不应该 posted。
Or do I need set up ServerSocket
?
没有。你为什么这么认为?
If use ServerSocket
I cannot use same port, right?
错了。
Because when I open ServerSocket
for listen first (ex. at port 17001), I can not use client socket to send request via port 17001 because that port is already used.
又错了。不是。
正如我上面所说,如果您没有 post 所有相关代码,就不可能进一步帮助您,但是这已经有足够多的错误,您真的需要重新开始。
我可以设置客户端Socket
向服务器发送请求(sendData()
方法)并正确读取接收到的消息(readData()
方法),但我每次都只收到消息我通过以下代码使用 MOBILE_REQUEST
字符串向服务器发送请求:
@Override
protected Boolean doInBackground(String... params) {
try {
mSocket = new Socket(
// PC Ip is 192.168.1.199
// It is the other device, Not be local host : 127.0.0.1
Pas.pas.getPcIP(), 17001);
DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());
String RESPONSE = null;
String MOBILE_BLOCK = "MobileBlock#";
// Converting collected data in byte array into String.
RESPONSE = sendData(mDos, MOBILE_BLOCK);
/**
* The result response from PC app in here
*/
// Log : response - #WindowsResp#192.168.1.199#
Log.i("", "response '" + RESPONSE + "'");
}
} catch (SocketTimeoutException e) {
IS_SOCKET_TIME_OUT = true;
e.printStackTrace();
} catch (ConnectException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
sendData()
方法 - 客户端向服务器发送请求并等待获取响应数据 - 字符串数据。
private String sendData(DataOutputStream mDos, String MOBILE_REQUEST) {
try {
// Log : MOBILE_REQUEST.getBytes() - [B@82f10f8
mDos.write(MOBILE_REQUEST.getBytes());
// todo I should set this sleep, bcs TCP has delay time,
// so i need set the delay time for client should receive data
// otherwise, sometimes I did not receive anything
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Log : #WindowsResp#192.168.1.199#
return new String(readData(mSocket));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
readData()
方法 - 从服务器接收后读取数据。
public static byte[] readData(Socket mSocket) {
/* Since data are accepted as byte, all of them will be collected in the
following byte array which initialised with accepted data length. */
DataInputStream mDis = null;
try {
mDis = new DataInputStream(mSocket.getInputStream());
// Log : mDis.available() - 23
byte[] data = new byte[mDis.available()];
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
// Log : data - [B@30c044a4
return data;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
我想要的是每次服务器通过单击按钮向我的套接字客户端发送消息时,套接字客户端应该接收它。但在上面的代码中,它不是。
请帮助我如何设置套接字客户端总是从服务器监听?
p/s : 或者我需要设置 ServerSocket
?如果使用 ServerSocket
我不能使用相同的端口,对吗?因为当我首先打开 ServerSocket
进行监听时(例如在端口 17001),我无法使用客户端套接字通过端口 17001 发送请求,因为该端口已被使用。
已更新
服务器(PC 应用程序 - 笔记本电脑设备)发送到客户端(移动设备 - Android)的方式是通过 Socket TCP,通过以下步骤:
1 - 客户端(Android 设备)建立到服务器(PC 应用程序)的 TCP 套接字连接(此连接永远不会关闭,直到在 onDestroy()
方法中退出应用程序)。
2 - 客户端向服务器发送请求,例如。 MOBILE_REQUEST = "MobileID#MobileIP#"
3 - 服务器收到客户端的请求,通过Socket连接回复客户端,实际上客户端正确接收到数据。前任。 "WindowsRep#WindowsIP"
这种方式对我不起作用,即使 socket TCP 连接没有关闭,getInputStream()
也没有关闭。在这种情况下:
服务器通过Socket连接向客户端发送字符串数据,客户端正确接收到数据。
我想要的是每一次"Server send string data to client via Socket connection, client received data correctly"。但就我而言,客户端仅在向服务器发送请求后才接收数据。
C# 服务器
服务器套接字
IPEndPoint ipe = new IPEndPoint("192.168.1.199", 17001);
svSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
svSocket.Bind(ipe);
服务器发送数据
string data_send = "#WBroad#" + "192.168.1.199" + "#";
byte[] byteData = Encoding.UTF8.GetBytes(data_send);
c.ClientSocket.Send(byteData);
由于您还没有 posted 发送代码,因此无法说出您为什么没有收到数据,但这里是对您所拥有内容的快速评论 posted:
// mSocket.setReuseAddress(true);
您已将其注释掉,但现在调用此方法将毫无意义。您必须将套接字构造为 new Socket()
,不带参数,然后调用此方法,然后调用 connect()
。由于您没有提供要重复使用的源端口或 IP 地址,因此它仍然毫无意义。
byte[] data = new byte[mDis.available()];
这完全是对 available()
的误用。它不提供消息长度。请参阅Javadoc。没有理由相信此时到达的任何数据,如果有,是一条完整的消息,或者只是一条消息。如果您需要消息,您将无法从 TCP 获得任何帮助:您必须自己实现它们。由于您的协议似乎是基于文本的,我建议您只使用行和 readLine()
,以及 BufferedReader
和 BufferedWriter
而不是 DataInput/OutputStreams
。并在套接字的生命周期内构造一次,而不是每个应用程序消息构造一次,否则您将丢失数据。
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
这个巨大的问题是它不会阻塞,因为大多数时候,available()
将为零,所以这个方法什么都不做除了 return 一个空的 byte[]
数组。
在任何情况下,这都完全等同于 mDis.readFully(data);
,只是效率低了数倍,但无论如何你都不应该这样做:见上文。
return data;
} catch (IOException e) {
e.printStackTrace();
}
return null;
这是不好的做法。你应该让IOException
被这个方法抛出,让调用者处理它。
mDos.write(MOBILE_REQUEST.getBytes());
见上文。这应该包括一个行终止符、一个长度字前缀或一些其他的消息定界方式。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
这种睡眠完全是浪费时间。和 space。去掉它。睡在网络代码中只是货物崇拜编程。
return new String(readData(mSocket));
这将抛出 NullPointerException
if readData()
returns null
,如果存在 IOException
,它会抛出 NullPointerException
,这是另一个原因让该方法传播该异常,而不是在内部捕获它并 returning null.
private boolean splitData(int mobile_send_request_case, String DATA) {
此方法与问题完全无关,不应该 posted。
Or do I need set up
ServerSocket
?
没有。你为什么这么认为?
If use
ServerSocket
I cannot use same port, right?
错了。
Because when I open
ServerSocket
for listen first (ex. at port 17001), I can not use client socket to send request via port 17001 because that port is already used.
又错了。不是。
正如我上面所说,如果您没有 post 所有相关代码,就不可能进一步帮助您,但是这已经有足够多的错误,您真的需要重新开始。