我正在开发Android服务器通信使用套接字和输入,输出流(没有包装类,如datainputstream,对象流等)
通信基于每边的三个线程(服务器有接受新套接字的额外线程)
第一个线程是控制器,它通过LinkedBlockingQueue接受来自接收者的消息,对它们做出反应,并通过LinkedBlockingQueue向发送者发送数据
第二个线程是接收器,它定期读取套接字(通过输入tream.read),如果有消息,它会通过LinkedBlockingQueue将消息传递给主管
当连接丢失时,客户端Android设备(已阻止input.read)立即抛出连接超时异常
第三个线程是发送者,它定期从LinkedBlockingQueue获取消息,并将数据发送到连接的另一边
问题是:防止客户端接收器抛出异常(这看起来像一些Android的东西,因为input.read单独不应该抛出任何异常相关的超时连接
这里是接收器代码:
public class Receiver implements Runnable {
private boolean run = true;
BlockingQueue<MessageQueue> queueReceiverOut;
InputStream in;
////////////////////////////// CONSTRUCTOR ////////////////////////////////
public Receiver(BlockingQueue<MessageQueue> queueReceiverOut, InputStream in) {
this.queueReceiverOut = queueReceiverOut;
this.in = in;
}
// ////////////////////////////// METHODS ////////////////////////////////
/**
* Runs when thread starts.
*/
public void run() {
int[] message = new int[2];
byte[] data;
MessageQueue msg;
try {
while(true) {
msg = new MessageQueue();
message = receiveMessage();
System.out.println("receives message");
if(message[0] != -1) {
System.out.println("receives full message");
if(message[1] != 0) {
data = receiveData(message[1]);
msg.setMessageType(message[0]);
msg.setDataLength(message[1]);
msg.setData(data);
queueReceiverOut.put(msg);
} else {
msg.setMessageType(message[0]);
msg.setDataLength(message[1]);
queueReceiverOut.put(msg);
}
}
}
} catch (IOException e) {
System.out.println("----disconnected-----");
try {
MessageQueue msgReceiverOut = new MessageQueue();
msgReceiverOut.setMessageType(SocketMessages.STATUS_OFFLINE);
queueReceiverOut.put(msgReceiverOut);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int[] receiveMessage() throws IOException {
int[] messageHead = new int[2];
messageHead[0] = in.read();
if(messageHead[0] != -1) {
System.out.println("received message with type : " + messageHead[0]);
int length1 = in.read();
int length2 = in.read();
int length3 = in.read();
int length4 = in.read();
messageHead[1] = ((length1 << 24) + (length2 << 16) + (length3 << 8) + (length4 << 0));
System.out.println(" with length : " + messageHead[1]);
}
return messageHead;
}
public byte[] receiveData(int length) throws IOException {
byte[] buffer = new byte[length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < length
&& (numRead = in.read(buffer,
offset, length - offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < length) {
throw new IOException("Could not completely read file ");
}
return buffer;
}
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
发件人:
public class Sender implements Runnable {
private boolean run = true;
BlockingQueue<MessageQueue> queueSenderIn;
BlockingQueue<MessageQueue> queueSenderOut;
OutputStream out;
////////////////////////////// CONSTRUCTOR ////////////////////////////////
public Sender(BlockingQueue<MessageQueue> queueSenderIn, BlockingQueue<MessageQueue> queueSenderOut, OutputStream out) {
this.queueSenderOut = queueSenderOut;
this.queueSenderIn = queueSenderIn;
this.out = out;
}
// ////////////////////////////// METHODS ////////////////////////////////
/**
* Runs when thread starts.
*/
@Override
public void run() {
MessageQueue msg;
try {
while(run) {
msg = queueSenderIn.poll(2, TimeUnit.SECONDS);
if(msg != null) {
sendMessage(msg.getMessageType(),msg.getDataLength());
if(msg.getDataLength()!=0) {
sendData(msg.getData());
}
}
}
Log.v(getClass().getName(),"sender destroyed");
} catch (IOException e) {
Log.v(getClass().getName(),"connection closed");
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendMessage(int messageType, int dataLength) throws IOException, InterruptedException {
MessageQueue msg = new MessageQueue();
Log.v(getClass().getName(), "sending message type : " + messageType);
out.write(messageType);
Log.v(getClass().getName(), "sending data with length : " +dataLength);
out.write((dataLength >>> 24) & 0xFF);
out.write((dataLength >>> 16) & 0xFF);
out.write((dataLength >>> 8) & 0xFF);
out.write((dataLength >>> 0) & 0xFF);
msg.setMessageType(messageType);
queueSenderOut.put(msg);
}
public void sendData(byte[] data) throws IOException {
String string = new String(data,"UTF-8");
Log.v(getClass().getName(), " with content : " + string);
out.write(data);
}
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
更新:因为误解了例外
在异常情况下,基础连接可能会被远程主机或网络软件中断(例如,TCP连接情况下的连接重置)。当网络软件检测到断开的连接时,以下内容适用于返回的输入流:
>
如果套接字上没有缓冲的字节,或者所有缓冲的字节都已被read占用,那么所有后续的read调用都将抛出IOException。
如果套接字上没有缓冲的字节,并且未使用close关闭套接字,那么available将返回0。
发件人:http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#getInputStream()
尤其是“后续电话”部分。这意味着,如果您已经在一个read
调用中阻塞,则上述关于read调用的条件(尚未)不适用。
到目前为止,解释是正确的。现在来看解决方案:你可以(多种可能性之一)定期发送消息,即使在通信空闲的时候。因此,您的发送方将检测到连接丢失,也可以关闭流中的连接。
编辑:为了更清楚一点...
然而
我想关键是(我假设)您的服务器进入读取并在那里停留很长时间,而您的客户机在连接中断时接收数据。因此,它将不断地从read
调用并返回。在等待读取解除阻塞时仍有可能发生连接丢失,但可能性要小得多。
我有一个使用Netty用Java设计的非常简单的服务器。我还使用Java NIO包编写了一个简单的客户端。我可以将Netty服务器与客户端连接起来,但当消息发送到服务器时,我会遇到以下例外情况: 我的输出: 我的服务器程序: 我的ServerHandler: 我的NIO Java客户端: 2)我正在使用LengthFieldBasedFrameDecoder和LengthPrepender来消除半
问题内容: 我目前处于论文项目的研究阶段。 我的项目是用于移动设备的票务预订系统,我选择了以Android为目标。 我预计需要具有中央服务器的客户端/服务器架构,因此目前正在研究Android如何与此类服务器进行通信。服务器将授予客户端访问票务信息的权限,客户端会将有关票务预订的信息发送到服务器。我正在寻找服务器的Java EE,因为Java是我最有经验的语言。 我知道Android附带了和以及一
问题内容: 所以现在,我正在制作一个基于客户端服务器应用程序的多线程。在服务器端,我为接受的每个连接创建了一个线程。 在线程类中,我创建了一种将命令发送到客户端的方法。我只想要的是如何将参数发送到所有正在运行的客户端?为简单起见,我只想使此服务器向所有连接的客户端发送消息。 我已经阅读了这篇文章,并从此链接中找到方法。但是,当我尝试使用自己的代码时,中没有类似的方法。 好的,这是我的服务器和线程示
本文向大家介绍python服务器与android客户端socket通信实例,包括了python服务器与android客户端socket通信实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python服务器与android客户端socket通信的方法。分享给大家供大家参考。具体实现方法如下: 首先,服务器端使用python完成,下面为python代码: 下面是Android代码: 安卓代
我对spring boot和SSL还很陌生。我已经开发了一个SSL rest web服务器,它具有服务器密钥存储库、私钥和服务器CA,并且能够正确地处理相互X.509证书身份验证。我已经测试过,它可以与Postman和Python客户机一起工作HTTPS请求,并且所有工作都正常,服务器和客户机都可以成功地交换和验证对方的证书。 但我的情况有点不同, 我已经创建并连接了一个Postgresql数据库
现在我的ServerSocket是这样的 一切正常,客户端连接,发送一些数据,服务器读取它,但我的问题是如何从我的服务器发送消息到所有的客户端?我目前保存客户端上的ArrayList,所以我可以只是循环,ArrayList打开一个作家和刷新它,但我想发送的数据,我得到我的ClientConnection类 我应该如何处理这个代码?在服务器类上完成的所有操作?或