gpt4 book ai didi

java - java中永久和持久的套接字连接

转载 作者:搜寻专家 更新时间:2023-10-31 08:14:52 27 4
gpt4 key购买 nike

我已经创建了一个客户端-服务器连接,类似于聊天系统。以前我在客户端使用一个while循环,它每次都在等待从控制台读取消息(当然服务器也有一个while循环来永远服务)。但是现在,我试图在 session 开始时先创建一个连接,然后在 session 期间偶尔发送一条消息,以便保持永久和持久的连接。

目前,如果没有while 循环,客户端会关闭连接,我不知道如何找到解决方法。

这是客户端代码:

import java.net.*;
import java.io.*;
public class ControlClientTest {
private Socket socket = null;
// private BufferedReader console = null;
private DataOutputStream streamOut = null;

public static void main(String args[]) throws InterruptedException {
ControlClientTest client = null;

String IP="127.0.0.1";
client = new ControlClientTest(IP, 5555);
}

public ControlClientTest(String serverName, int serverPort) throws InterruptedException {
System.out.println("Establishing connection. Please wait ...");
try {
socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}

String line = "";
// while (!line.equals(".bye")) {
try {
Thread.sleep(1000);
//TODO get data from input
// line = console.readLine();
line="1";
if(line.equals("1"))
line="1,123";
streamOut.writeUTF(line);
streamOut.flush();
} catch (IOException ioe) {
System.out.println("Sending error: " + ioe.getMessage());
}
// }
}

public void start() throws IOException {
// console = new BufferedReader(new InputStreamReader(System.in));
streamOut = new DataOutputStream(socket.getOutputStream());
}

}

这是服务器代码:

import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ControlServer {
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;

public static void main(String args[]) {

ControlServer server = null;
server = new ControlServer(5555);
}

public ControlServer(int port) {
try {
System.out
.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done) {
try {
String line = streamIn.readUTF();
// TODO get the data and do something
System.out.println(line);

done = line.equals(".bye");
} catch (IOException ioe) {
done = true;
}
}
close();
} catch (IOException ioe) {
System.out.println(ioe);
}

}


public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
}
public void close() throws IOException {
if (socket != null)
socket.close();
if (streamIn != null)
streamIn.close();
}

}

最佳答案

我想总结一些我日常应用的有关 TCP/IP 连接稳定性的良好做法。

最佳实践 1:内置 Keep-Alive

socket.setKeepAlive(true);

它会在一段时间不活动后自动发送信号并检查回复。但是,保持 Activity 时间间隔取决于操作系统,并且有一些缺点。但总而言之,它可以提高连接的稳定性。

最佳实践 2:SoTimeout

无论何时执行read(或在您的情况下为readUTF),您的线程实际上将永远阻塞。根据我的经验,这是一种不好的做法,原因如下: 很难关闭您的应用程序。仅仅调用 socket.close() 是不干净的。

一个干净的解决方案,是一个简单的读取超时(例如 200 毫秒)。您可以使用 setSoTimeout 方法执行此操作。当 read() 方法超时时,它将抛出一个 SocketTimeoutException。 (它是 IOException 的子类)。

socket.setSoTimeout(timeoutInterval);

这是一个实现循环的例子。请注意 shutdown 条件。只需将其设置为 true,您的线程就会平静地结束。

while (!shutdown)
{
try
{
// some method that calls your read and parses the message.
code = readData();
if (code == null) continue;
}
catch (SocketTimeoutException ste)
{
// A SocketTimeoutExc. is a simple read timeout, just ignore it.
// other IOExceptions will not be stopped here.
}
}

最佳实践 3:Tcp 无延迟

当您经常连接需要快速处理的小命令时,请使用以下设置。

try
{
socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}

最佳实践 4:心跳

实际上还有很多场景还没有涉及。

例如,其中一个是服务器应用程序,旨在一次仅与 1 个客户端通信。有时他们接受连接甚至接受消息,但从不回复它们。

另一个:有时当您失去连接时,您的操作系统实际上可能需要很长时间才能注意到这一点。可能是由于良好做法 3 中描述的缺点,而且在更复杂的网络情况下(例如使用 RS232 转以太网转换器、VMware 服务器等),这种情况经常发生。

这里的解决方案是创建一个线程,每隔 x 秒发送一条消息,然后等待回复。 (例如,每 15 秒)。为此,您需要创建第二个线程,它每 15 秒发送一次消息。其次,你需要稍微扩展良好实践2的代码。

  try
{
code = readData();

if (code == null) continue;
lastRead = System.currentTimeMillis();

// whenever you receive the heart beat reply, just ignore it.
if (MSG_HEARTBEAT.equals(code)) continue;

// todo: handle other messages
}
catch (SocketTimeoutException ste)
{
// in a typical situation the soTimeout is about 200ms
// the heartbeat interval is usually a couple of seconds.
// and the heartbeat timeout interval a couple of seconds more.
if ((heartbeatTimeoutInterval > 0) &&
((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
{
// no reply to heartbeat received.
// end the loop and perform a reconnect.
break;
}
}

您需要决定是由您的客户端还是服务器发送消息。这个决定并不那么重要。但是例如如果您的客户端发送消息,那么您的客户端将需要一个额外的线程来发送消息。您的服务器应在收到消息时发送回复。当您的客户端收到答案时,它应该只是 continue (即见上面的代码)。双方都应该检查:“已经多久了?”以非常相似的方式。

关于java - java中永久和持久的套接字连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29685705/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com