首先:我希望我的英语不是那么糟糕(也许它很有趣;德语语法有英语词汇)
我在java for android中编写一个服务器,它与在WindowsCE 5上运行的c#编写的客户端进行通信。最大的问题是,有时特别或者可能只有在网络不稳定时我的java服务器仍会阻塞accept-Method也在客户端发送数据时。我通过关闭和我的虚拟路由器模拟不稳定的网络,两个设备通过它进行通信。我也可以认识到c#-program在写入或读取方法中挂起,或者在网络开启且我的服务器在预期端口上听到时也会抛出IOException。
以下是客户端的源代码:
一些信息: 1.它仅发送10000条消息用于测试
static void Main(string[] args)
{
string server = ...;
int port = 12000;
String outputStr = "";
NetworkStream stream = null;
for (int i = 0; i < 10000; i++)
{
TcpClient client = null;
String messageToSend = ...
try
{
IPAddress ipAddress = IPAddress.Parse(server);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
AutoResetEvent connectDone = new AutoResetEvent(false);
client = new TcpClient();
client.Client.BeginConnect(ipEndPoint,
new AsyncCallback(
delegate(IAsyncResult ar)
{
try
{
client.Client.EndConnect(ar);
connectDone.Set();
}
catch (Exception ex)
{}
}
), client.Client);
if (!connectDone.WaitOne(5000, false))
{
outputStr = "NOTConnected";
}
Byte[] data = System.Text.Encoding.UTF8.GetBytes(messageToSend);
stream = client.GetStream();
try
{
stream.Write(data, 0, data.Length);
data = new Byte[2048];
int bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.UTF8.GetString(data, 0, bytes);
outputStr = responseData;
}
catch (IOException ex)
{
outputStr = ex.Message;
}
}
}
catch (SocketException ex)
{
outputStr = ex.Message;
}
catch (Exception ex)
{
outputStr = ex.Message;
}
finally
{
if (stream != null) stream.Close();
}
System.Threading.Thread.Sleep(200);
}
Console.WriteLine("\n Press Enter to continue... " + outputStr);
Console.Read();
}
我的服务器源代码:
一些信息。我的servlet通常是一个内部类,首先检查设备是否连接到路由器。如果是它开始在这里的端口。如果不是,则进入等待模式(参见_sendToSleep())。如果重新连接设备,活动可以通过通知唤醒它。如果它再次失去连接,那么Activity将通过关闭套接字导致SocketException,以便servlet可以离开accept方法。
public class ServletThread extends Thread {
private int port;
private ServerSocket serverSocket;
private Socket socket;
public ServletThread(int port) throws IOException {
super();
this.port = port;
serverSocket = new ServerSocket(port);
}
private void checkConnectivity(BufferedWriter out) {
try {
String outgoingMsg = "connected";
out.write(outgoingMsg);
out.flush();
} catch (IOException e) {
Log.e(TAG, "connectivity exception " + e.getMessage());
}
}
private void readStream(Scanner scanner) throws IOException {
String str = "";
while (scanner.hasNext()) {
str += scanner.nextLine();
}
final String fTicket = str;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (MyActivity.this.isFinishing()) {
return;
}
// do something
}
});
}
private void _sendToSleep() {
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
this.interrupt();
}
}
@Override
public void interrupt() {
super.interrupt();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
Log.e(TAG, ""+e.getMessage());
}
}
}
@Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch (IOException ex) {
Log.e(TAG,""+ex.getMessage());
}
while (!isInterrupted()) {
if (connectionState != NetworkInfo.State.CONNECTED) {
_sendToSleep();
} else {
BufferedWriter out = null;
Scanner scanner = null;
try {
socket = serverSocket.accept();
out = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
scanner = new Scanner(socket.getInputStream());
checkConnectivity(out);
readStream(scanner);
} catch (IOException ex) {
Log.e(TAG, ex.getMessage() + "");
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "exception on close socket " + e.getMessage());
}
}
if (scanner != null) {
scanner.close();
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
Log.e(TAG, ""+e.getMessage());
}
}
}
}
}
}
}
隔离bug之后,我做了一些更改:
c#而不是stream = client.getStream
(using Stream = client.getStream()) {
...
stream.WriteTimeout = 1000;
stream.ReadTimeout = 1000;
...
}
在_sendToSleep()中的java更改
private void _sendToSleep() {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
Log.e(TAG, "failed to close serverSocket " + e.getMessage());
}
}
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
this.interrupt();
}
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
Log.e(TAG, "failed to open serversocket " + e.getMessage());
}
}
它变得更好,意味着,我无法重现这个问题。
我的问题:
为什么客户端挂起? (重新连接几次后,socketserver和wlan-adapter之间的servlet端和客户端可能出现同步问题,这样servlet无法获取任何数据???) 并且我的更改可以解决问题。
期待你的感谢!