- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要一些建议并帮助解决我正在开发的蜂窝调制解调器项目的客户端/服务器交互问题。客户端和服务器都是用Java编写的。
我需要建议的问题如下:
(1) 我正在寻求建议,了解我所采取的方法是否能够扩展大文件(要遵循的代码),特别是在网络可能意外退出的蜂窝网络环境中。大文件约为 1GB。大文件表示从服务器传输到客户端的图像。这代表了最坏的情况。基本情况包含相对较小的文件,其中包含 GPS 数据和时间戳信息。这些文件可能在 KB 到几 MB 范围内,并且经常传输。
(2) 需要有关客户端/服务器代码故障排除的建议。即使这种方法不适用于较大的文件,我也希望让代码适用于基本案例,以支持在不久的将来进行概念验证测试。概念验证不需要软件更新。
客户端/服务器交互的背景知识。客户端联系服务器。服务器检测到客户端请求,启动一个新线程来处理客户端。客户端传输序列化数据包。数据包包含一些 header 信息(文件大小、crc、文件类型)和数据有效负载。收到数据包对象后,服务器验证 crc 和文件大小是否与 header 中包含的值匹配。服务器用数据包对象进行响应,该数据包对象指示传输是否有效。如果客户端收到来自服务器的有效响应,则客户端会发送一个再见数据包以关闭 session 。如果服务器的响应无效,客户端将重新发送数据,并在 x 次失败尝试后最终退出。最终,客户端将从服务器获取一组指令,这些指令可以指示它上传日志文件、下载新的 .jre 文件,甚至新的固件镜像。
这是我在服务器代码上遇到的错误:
Feb 16, 2013 7:36:40 AM noaa.logbook.server.ServerConnectionHandler run
SEVERE: null
java.io.EOFException
at
java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1296)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at noaa.logbook.server.ServerConnectionHandler.run(ServerConnectionHandler.java:69)
at java.lang.Thread.run(Thread.java:662)
数据随着服务器到达,看起来下次我尝试读取 objectinputstream 上的对象时发生异常,这是再见数据包。
客户端代码:
public static boolean clientTransmit(Socket sockToServer, String fileName, int dataPacketType, String id, String fileTimeStamp) {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
//TCPConnection tcpConn = null;
DataPacket packet = null;
File inputFile = new File(fileName);
boolean fileExists = inputFile.exists();
int size = 0;
int failedAttempts = 0;
String contents = null;
byte[] ref = null;
boolean success = false;
boolean bye = false;
try
{
sockToServer.setSoTimeout(5000);
if ((sockToServer.isConnected()) && (fileExists)) {
System.out.println("LogBookClientCommunications: Connected to Server");
System.out.print("Stage 0");
contents = readFile(fileName);
packet = LogBookUtilities.packageDataPacket(DataPacket.UPLOAD_DATA, contents, LogBookClient.SOFTWARE_VERSION, LogBookClient.serialNumber);
oos = new ObjectOutputStream(sockToServer.getOutputStream());
oos.writeObject(packet);
oos.flush();
System.out.println("LogBookClientCommunications: Sending DataPacket");
ois = new ObjectInputStream(sockToServer.getInputStream());
while(!success && failedAttempts < 3) {
Object object = ois.readObject();
if (object instanceof DataPacket) {
System.out.println("LogBookClientCommunications: Received a DataPacket Object");
DataPacket inPacket = (DataPacket)object;
byte[] compressedByteRef = inPacket.getDataArray();
boolean sizeValid = verifySize(compressedByteRef, inPacket.getLength());
boolean crcValid = verifyCRC(inPacket);
if ((sizeValid) && (crcValid)) {
System.out.println("LogBookClientCommunications: Size & CRC Valid");
String uncompressed = new String(uncompress(compressedByteRef));
String[] strRef = lookupResponsePairs(dataPacketType);
if (uncompressed.equals(strRef[0])) {
success = true;
System.out.println("LogBookClientCommunications: File arrived uncorrupted");
//tcpConn.disconnect();
} else if (uncompressed.equals(strRef[1])) {
success = false;
failedAttempts++;
System.out.println("LogBookClientCommunications: File arrived corrupted");
}
} else {
success = false;
failedAttempts++;
if (sizeValid)
System.out.println("LogBookClientCommunications: CRC InValid");
else
System.out.println("LogBookClientCommunications: Size InValid");
}
}//end if object instanceof
else {
System.out.println("LogBookClientCommunications: Not a DataPacket Object");
failedAttempts++;
}
}//while
//Close Connection by sending bye
System.out.println("LogBookClientCommunications: Sending Good Bye...");
DataPacket goodbye = LogBookUtilities.packageDataPacket(DataPacket.RESPONSE, quit", LogBookClient.SOFTWARE_VERSION, LogBookClient.serialNumber);
oos.writeObject(goodbye);
oos.flush();
}
else
{
System.out.println("LogBookClientCommunications: Failed to Connect or File Did Not Exist");
success = false;
}
}
catch (ClassNotFoundException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
oos.close();
ois.close();
sockToServer.close();
} catch (IOException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
}
}
return success;
}
服务器连接处理程序代码:
public void run()
{
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
int failedAttempts = 0;
boolean success = false;
boolean sendResponse = false;
Socket soc = getSocket();
Object obj = new Object();
long time = System.currentTimeMillis();
DataPacket inPacket = null;
DataPacket outPacket = null;
try {
System.out.println("Server Connection Handler: Receiving Connection From - " + soc.getRemoteSocketAddress());
soc.setSoTimeout(15000);
oos = new ObjectOutputStream(soc.getOutputStream());
oos.flush();
ois = new ObjectInputStream(soc.getInputStream());
if (ois == null | oos == null) {
System.out.println("Server Connection Handler: Successfull Opened Streams");
if (ois == null) { System.out.println("Server Connection Handler: ObjectInputStream Failed to Open");}
else {System.out.println("Server Connection Handler: ObjectOutputStream Failed to Open"); }
}
while (true) {
inPacket = (DataPacket)ois.readObject();
boolean validPacket = LogBookUtilities.isPacketValid(inPacket);
if (validPacket) {
if(inPacket.getField() == DataPacket.RESPONSE) {
byte[] ref = inPacket.getDataArray();
String data = LogBookUtilities.uncompress(ref);
if (data.equalsIgnoreCase("bye")) {
System.out.println("Server Connection Handler: Bye....");
break;
}
}
else if (inPacket.getField() == DataPacket.UPLOAD_DATA) {
System.out.println("Server Connection Handler: Writing data to file");
LogBookUtilities.processClientPacket(inPacket);
System.out.println("Server Connection Handler: File Successfully Transfered");
outPacket = LogBookUtilities.makeResponse(inPacket.getField(), true, LogBookServer.SOFTWARE_VERSION, LogBookServer.ID);
sendResponse = true;
}
}
else {
if (inPacket.getField() == DataPacket.UPLOAD_DATA) {
sendResponse = true;
outPacket = LogBookUtilities.makeResponse(inPacket.getField(), true, LogBookServer.SOFTWARE_VERSION, LogBookServer.ID);
}
}
if (sendResponse) {
oos.writeObject(outPacket);
oos.flush();
}
}//end while
}
catch (ClassNotFoundException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
try {
ois.close();
oos.close();
soc.close();
}
catch (IOException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
服务器代码:
public class LogBookServer
{
public static final String ID = "666666";
public static final String SOFTWARE_VERSION = "0.02";
public static final String VFILE = "vFile";
public static final String DASH = "-";
public static final String DATEXT = ".dat";
public static final int FAILED_THRESHOLD = 3;
private int port = 6767;
private String ip = "";
public int getListeningPort() {
return this.port;
}
public void setListeningPort(int port) {
this.port = port;
}
public void run()
throws Exception
{
Selector acceptSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(lh, this.port);
ssc.socket().bind(isa);
SelectionKey acceptKey = ssc.register(acceptSelector, 16);
int keysAdded = 0;
while ((keysAdded = acceptSelector.select()) > 0)
{
Set readyKeys = acceptSelector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey sk = (SelectionKey)i.next();
i.remove();
ServerSocketChannel nextReady = (ServerSocketChannel)sk.channel();
Socket s = nextReady.accept().socket();
handleConnection(s);
}
}
}
void handleConnection(Socket socket)
{
System.out.println("hadling connection....");
ServerConnectionHandler connectionHandler = new ServerConnectionHandler(socket);
new Thread(connectionHandler).start();
}
}
最佳答案
在您的客户端中,您有(为了可读性分成不同的行):
DataPacket goodbye =
LogBookUtilities.packageDataPacket(DataPacket.RESPONSE,
"quit",
LogBookClient.SOFTWARE_VERSION,
LogBookClient.serialNumber);
然后在您的服务器中您有:
if (data.equalsIgnoreCase("bye")) {
其中哪一个与另一个不同? ;)
您的服务器读取“再见”数据包,但无法识别它,然后再次循环并尝试从关闭的套接字读取数据。很快,IOException
。
至于你的“可扩展性”问题……与其说是效率,不如说是问题。如果您担心网络会从您的脚下掉线,那么发送序列化对象可能不是最佳选择。无法恢复 - 部分发送必须完全重新发送,如果它是您所说的一大堆数据……那很糟糕。您最好使用具有合理缓冲区大小的 OutputStream
的 write()
方法。这将允许您跟踪已发送的数据,并在网络恢复后恢复传输(显然,这将需要在客户端和服务器之间实现一些逻辑,以便您可以弄清楚服务器已经收到了什么网络故障的情况下)。
关于java - 针对蜂窝调制解调器项目的客户端/服务器交互故障排除的建议和帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14915962/
我是一个相对较新的程序员; CS 学士学位,大学毕业大约 2 年,主要使用 C# 中的 .NET。我对 SQL 交互/脚本编写相当流利,并且对 ASP.NET 做了一些工作(主要是维护现有站点)。 我
我计划开发一个简单的解决方案,使我能够即时执行非常基本的视频流分析。我以前从未做过类似的事情,因此这是一个非常笼统和开放的问题。主要重点是检查流是否正常运行,例如 - 卡住帧、黑屏以及音频是否存在。同
我正在考虑重组一个大型 Maven 项目...... 我们当前结构的基本概述: build [MVN plugins, third party dependency management]:5.1
我需要有关附加查询的建议。该查询执行了一个多小时,并根据解释计划进行了全表扫描。我对查询调优还很陌生,希望得到一些建议。 首先,为什么我要进行全表扫描,即使我使用的所有列都在其上创建了索引。 其次,有
我正在做一个项目,我需要在 4 个模型之间创建三个多对多关系。这是它的过程: 常见问题类别可以有许多常见问题子类别,反之亦然。 常见问题组可以有许多常见问题的子类别,反之亦然。 常见问题可以有许多常见
对于代码大小比语音质量更重要的 PIC 和/或 ARM 嵌入式系统,是否有任何易于使用的免费或廉价的语音合成库?现在似乎 1 meg 的封装被认为是“紧凑的”,但很多微 Controller 都比它小
我们正在使用 Solr 建议器功能进行 businessName 查找。当用户输入查询以及匹配的名称时,我们希望 solr 发送来自个人资料的其他属性,如 id、地址、城市、州、国家等字段。 我尝试使
我正在构建一个用户界面。我的计划将包括 4 个主要部分: 1) 顶部菜单 - TMainMenu。一个窗口的顶部 2) 主菜单 - TTreeView。一个窗口的左边。 TreeView的每一项=对应
我的公司需要一个任务管理系统来处理从“为X购买一台计算机”到“将一个人转移到另一个国家”这样简单的场景。简单的场景是由一个人处理的单个任务,而更大的任务可以分解为在工作流程中委派给多个人的多个子任务。
MarkLogic 服务器的林大小与实际内存的建议比率是多少?例如,我目前有一个 190GB 的数据库,并且该数据库随着时间的推移而不断增长。由于数据库会不断增长,我最终需要对该数据库进行集群。因此,
去年我收到了一个礼物,它是一个索尼 CMT700Ni 音频站,支持 wifi。它还具有类似于广播的功能,称为“PartyStreaming”。我目前正在挖掘内部,探索它,所以也许我可以结束拥有自己的“
有没有我可以阅读的研究论文/书籍可以告诉我针对手头的问题哪种特征选择算法最有效。 我试图简单地将 Twitter 消息识别为 pos/neg(首先)。我从基于频率的特征选择开始(从 NLTK 书开始)
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在浏览 stackoverflow 以查找有关使用 jUnit 进行测试的常见建议,但仍然有几个问题。我知道,如果要测试的方法很复杂,最好的方法是将其分成小的单独部分并测试每个部分。但问题是 -
我有一个方法如下 public List> categorize(List customClass){ List> returnValue = new ArrayList<>();
我的问题是,当按照下面的程序合并时,在最佳实践场景中,“将分支折叠回主干”程序的最后一步是正确的方法吗? 我已经使用 svn 很多年了。在我的个人项目中,我总是毫不犹豫地在主干上愉快地进行修改,并且在
我读过 UINavigationController当您想从 n 个屏幕跳转到第一个屏幕时,这是最佳选择。这样做需要以下代码: NSMutableArray *array=[[NSMutableArr
我有一个文件输入类。它在构造函数中有一个字符串参数来加载提供的文件名。但是,如果文件不存在,它就会退出。如果文件不存在,我希望它输出一条消息 - 但不确定如何...... 这是类(class): pu
我希望创建一个“您访问过的国家/地区” map - 就像您可能在 Facebook、TravelAdvisor 和诸如此类的网站上看到的那样。 我尝试过不同的闪光灯套件,但它们并不像我希望的那样先进。
我需要一些关于如何处理我想用 Perl 编写的脚本的建议。基本上我有一个看起来像这样的文件: id: 1 Relationship: "" name: shelby pet: 1
我是一名优秀的程序员,十分优秀!