我已经编写了一些服务器端套接字处理代码,我担心我的数据包可能并不总是返回到客户端。我正在记录我的所有事件,并且在我的日志文件中它说我正在发送信息。但是客户端也在记录事件,并且在他们的日志中他们说他们没有收到任何东西。
我发送数据的代码如下:
public void write(Packet packet) {
String data = packet.serialize();
log("Send=[" + data + "]", "Write"); // log to file
try {
_writer.write(data);
_writer.flush();
} catch (Exception ex) {
log(ex, "write");
}
}
每个套接字都是在一个新线程上创建的,我立即像这样创建我的作者和读者(在公共运行方法中):
// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
.getOutputStream()));
_reader = new SocketReader(_socket);
SocketReader 只是我为侦听响应而创建的一个包装类,它有一个公共读取方法,如下所示:
public String read() throws IOException, SocketTimeoutException {
_socket.setSoTimeout(_timeOut);
if(_reader == null)
_reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
// read from the stream
return new PacketDataInputStream(_reader).read();
}
PacketDataInputStream 包装类:
BufferedReader _reader = null;
public PacketDataInputStream(BufferedReader reader)
{
_reader = reader;
}
public String read() throws IOException, SocketException {
StringBuilder builder = new StringBuilder();
int c = 0;
while((c = _reader.read()) != -1)
{
char ch = (char)c;
builder.append(ch);
if(ch == PacketConstants.ETX)
break;
}
if(builder.length() > 0)
return builder.toString();
else
return null;
}
我认为创建实际套接字侦听器对象的方式非常标准:
InetAddress address = InetAddress.getByName(IP);
server = new ServerSocket( port, 0, address);
// My own manager class to handle all the sockets connected
WebSocketManager manager = new WebSocketManager(this);
Socket connection = null;
while(bContinue)
{
connection = server.accept();
if(bContinue) {
// assign the socket to a new thread and start
// that thread
manager.newSocket(connection);
} else {
connection.close();
}
}
- 有可能我使用了错误的对象来发回数据。
- 我什至应该使用缓冲写入器和读取器吗?我曾认为这些是最好的方法,但现在我不太确定。
需要注意的是,这种情况并非一直发生,只是偶尔发生。可能是客户端代码有错误,但我需要确保在返回它们之前我做得正确。
此代码在Linux Ubuntu服务器上运行。记录发生在一个文本文件中,没有什么特别的。我的日志文件显示Send=""数据返回客户端并且没有异常,因此看起来好像 .write 和 .flush() 有效?套接字连接是持久的,仅由客户端和/或网络问题关闭。
更新-----客户端代码------:
我确实设法获得了一些客户端代码,以了解他们如何处理数据的发送和接收(以防万一他们更明显)。客户端实际上是通过Android 设备连接到该服务器(如果有帮助的话)。
套接字的创建
static final int BUFFER_SIZE = 20000; // Maximum packet size
java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
发送:
try {
// Send the packet:
OutputStream stream = socket.getOutputStream();
stream.write(p.getByteArray ());
stream.flush();
// Update the time:
lastPacketSendTime = new Date ();
} catch (IOException e) {
setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
return false;
}
接收:
socket.setSoTimeout(timeout);
// Get the reader:
inputStream = socket.getInputStream();
while (true) {
// Get the next character:
int value = inputStream.read();
// Check for -1, indicating that the socket is closed:
if (value == -1) {
// The socket is closed remotely, so close it locally as well:
disconnect();
inputStream = null;
return null;
}
// ... and a bunch of other stuff to handle the actual data
}
编辑 11 月 14 日: 这实际上被证明是一个更大的问题。客户端日志和服务器日志似乎都在发送。但有时数据似乎没有通过,或者如果确实如此,它有时会延迟 10 - 30 - 60 秒。
如果需要,我可以提供更多信息。