在java中设置套接字选项
我有一个 Java 服务器,它监听特定端口的传入连接。一切都按预期工作,我的客户端连接到服务器,我可以在它们之间发送数据。
我的问题是,当我关闭客户端,再次打开它并尝试重新连接时,它不会连接(我的服务器始终保持打开状态)。
为了重新连接,我必须再次重新启动服务器。
所以我尝试在服务器端执行此操作:
InetSocketAddress serverAddr = new InetSocketAddress(serverIpAddress, serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
//I tries setting up a reuse option
serverSocket.bind(serverAddr);
即使在 setReuseAddress()
之后,除非重新启动服务器,否则我的客户端也不会连接! 有谁知道如何做到这一点?
EDIT2:
try {
while(true){
clientSocket = serverSocket.accept();
System.out.println("S-a conectat clientul de monitorizare!");
os=new ObjectOutputStream(clientSocket.getOutputStream());
try{
coord=(Coordinate)queue.take();
System.out.println(coord.getLat()+coord.getLon()+coord.getVit()+coord.getwId()+coord.getime());
os.writeObject(coord);
os.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
try {
clientSocket.close();
os.close();
}catch(Exception e1) {
e1.printStackTrace();
}
}
新编辑:
线程池服务器:
主要:
ThreadPooledServer server = new ThreadPooledServer(queue,7001); 新线程(服务器).start();
ThreadPooledServer:
公共类 ThreadPooledServer 实现 Runnable {
protected ExecutorService threadPool =
Executors.newFixedThreadPool(5);
public void run() {
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
System.out.println("Serverul asteapta clienti spre conectare");
clientSocket = this.serverSocket.accept();
clientconnection++;
System.out.println("Serverul a acceptat clientul cu numarul:"
+ clientconnection);
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
WorkerRunnable workerRunnable = new WorkerRunnable(queue,clientSocket);
this.threadPool.execute(workerRunnable);
}
System.out.println("Server Stopped.");
}
公共同步 void stop() { this.isStopped = true;
try {
this.threadPool.shutdown();
}
catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
私有无效 openServerSocket() {
try {
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,
serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(serverAddr);
} catch (IOException e) {
throw new RuntimeException("Cannot open port", e);
}
}
this.serverSocket.close();
I have a server in Java which listens for incoming connection to a specific port. And everything works as expected, my clients connect to the server and I'm able to send data between them.
My problem is that, when I shut down my client, turn it on again and try to reconnect, it won't connect (my server stays on all the time).
For me to reconnect, I have to restart my server again.
So I tried doing this on my server side:
InetSocketAddress serverAddr = new InetSocketAddress(serverIpAddress, serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
//I tries setting up a reuse option
serverSocket.bind(serverAddr);
Even after setReuseAddress()
my client won't connect unless I restart my server!
Has anyone any idea of how could that be done?
EDIT2:
try {
while(true){
clientSocket = serverSocket.accept();
System.out.println("S-a conectat clientul de monitorizare!");
os=new ObjectOutputStream(clientSocket.getOutputStream());
try{
coord=(Coordinate)queue.take();
System.out.println(coord.getLat()+coord.getLon()+coord.getVit()+coord.getwId()+coord.getime());
os.writeObject(coord);
os.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
try {
clientSocket.close();
os.close();
}catch(Exception e1) {
e1.printStackTrace();
}
}
New edit:
Thread pool server:
Main:
ThreadPooledServer server = new ThreadPooledServer(queue,7001);
new Thread(server).start();
ThreadPooledServer:
public class ThreadPooledServer implements Runnable {
protected ExecutorService threadPool =
Executors.newFixedThreadPool(5);
public void run() {
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
System.out.println("Serverul asteapta clienti spre conectare");
clientSocket = this.serverSocket.accept();
clientconnection++;
System.out.println("Serverul a acceptat clientul cu numarul:"
+ clientconnection);
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
WorkerRunnable workerRunnable = new WorkerRunnable(queue,clientSocket);
this.threadPool.execute(workerRunnable);
}
System.out.println("Server Stopped.");
}
public synchronized void stop() {
this.isStopped = true;
try {
this.threadPool.shutdown();
}
catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,
serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(serverAddr);
} catch (IOException e) {
throw new RuntimeException("Cannot open port", e);
}
}
this.serverSocket.close();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在您的
run
方法中,您接受一个客户端,然后进入无限循环,尝试将数据写入ObjectOutputStream
。当客户端关闭连接时,会引发异常,因为您无法再写入流。此时,我们脱离了无限循环 (while(true) { .. }
),并且run
方法结束。如果您想继续接受客户端,我建议您将
while
循环移至代码顶部,准确地说是在接受之上。下面的伪代码(注意:我没有捕获任何异常等):
In your
run
method you accept one client and then go in to an endless loop, trying to write data to theObjectOutputStream
. When the client closes the connection an exception is thrown because you can no longer write to the stream. At this point we're out of the endless loop(while(true) { .. }
) and therun
method ends.If you want to keep accepting clients I suggest you move the
while
loop to the top of your code, above the accept to be exact.Pseudo-ish code below(note: I'm not catching any exceptions etc.):
您的服务器是否出于某种目的而采用单线程(您一次只接受一个客户端)?通常,服务器会为每个连接生成一个单独的线程,因此它可以更频繁地侦听传入连接,因此如果客户端的连接抛出任何错误,也不会影响侦听套接字。目前,您的服务器将仅侦听一个连接,如果处理客户端连接时发生异常,只需继续前进,不再侦听。在伪代码中,典型的服务器如下:
服务器侦听线程 (主线程)
服务器客户端连接线程
[1] 如果你的服务器只处理一个客户端,它应该拒绝连接,这样客户端就不会无缘无故地等待
[2] 如果异常与套接字无关,则应该通过以下方式警告客户端在关闭套接字之前对套接字进行最终写入
客户端线程(在客户端)
[4],因为服务器应该首先写入套接字,客户端应该在尝试写入任何内容之前从中读取任何欢迎消息或错误消息。
Is your server single threaded for a purpose (do you only accept one client at a time) ? Usually, servers will spawn a separate thread for every connections, so it can listen more often for incoming connections, and so if the client's connection throws any errors, it won't affect the listening socket. At the moment, your server will listen to only one connection, and if an exception occurs handling the client's connection, simply move on and never listen again. In pseudocode, a typical server is like :
Server listening thread (main thread)
Server client connection thread
[1] if your server handles only one client, it should refuse the connection, so the client doesn't wait for no reason
[2] if the exception is not about the socket, the client should be warned by a final write to the socket before closing it
Client thread (on the client's side)
[4] since the server should write to the socket first, the client should read from it for any welcome message or error messages before attempting to write anything.