java.net.BindException:地址已在使用中:无法绑定
对不起,我已经搜索过了,但似乎所有的答案都不能解决我的问题。我在尝试创建ServerSocket以答复多个客户端消息时遇到此错误 我的服务器代码:java.net.BindException:地址已在使用中:无法绑定,java,sockets,network-programming,serversocket,Java,Sockets,Network Programming,Serversocket,对不起,我已经搜索过了,但似乎所有的答案都不能解决我的问题。我在尝试创建ServerSocket以答复多个客户端消息时遇到此错误 我的服务器代码: package Server; import java.net.*; import java.io.*; public class Server { public final static int defaultPort = 7; public static void main(String[] args) {
package Server;
import java.net.*;
import java.io.*;
public class Server {
public final static int defaultPort = 7;
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(defaultPort);
int i = 0;
while (true) {
try {
System.out.println("Server is running on port "
+ defaultPort);
Socket s = ss.accept();
System.out.println("Client " + i + " connected");
RequestProcessing rp = new RequestProcessing(s, i);
i++;
rp.start();
} catch (IOException e) {
System.out.println("Connection Error: " + e);
}
}
} catch (IOException e) {
System.err.println("Create Socket Error: " + e);
} finally {
}
}
}
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
DatagramSocket ds = new DatagramSocket(7);
while (true) {
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
String theString = new String(incoming.getData(), 0,
incoming.getLength());
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
ds.close();
break;
}
theString = theString.toUpperCase();
DatagramPacket outsending = new DatagramPacket(
theString.getBytes(), incoming.getLength(),
incoming.getAddress(), incoming.getPort());
System.out.println("Server reply to Client "
+ clientNo + ": " + theString);
ds.send(outsending);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
和我的客户代码:
package Client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
public class Client extends Object {
public final static int serverPort = 7;
public static void main(String[] args) {
try {
DatagramSocket ds = new DatagramSocket();
InetAddress server = InetAddress.getByName("192.168.109.128");
Socket s = new Socket("192.168.109.128", 7);
String theString = "";
do {
System.out.print("Enter message: ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
theString = br.readLine();
byte[] data = theString.getBytes();
DatagramPacket dp = new DatagramPacket(data, data.length,
server, serverPort);
ds.send(dp);
System.out.println("Sent to server server: " + theString);
byte[] buffer = new byte[6000];
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.length);
ds.receive(incoming);
System.out.print("Server reply: ");
System.out.println(new String(incoming.getData(), 0, incoming
.getLength()));
} while (!"quit".equals(theString));
s.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
通过第一个客户端连接,它可以顺利工作。但是从第二个客户端,它抛出java.net.BindException:Address ready in use:Cannot bind。
第二个客户端也可以发送和接收消息,但客户端号仍然为0
Server is running on port 7
Client 0 connected
Server is running on port 7
Client 0 sent: msg 0
Server reply to Client 0: MSG 0
Client 1 connected
Server is running on port 7
java.net.BindException: Address already in use: Cannot bind
Client 0 sent: msg 1 <<-- this one is sent from client 1 but Client No is 0
Server reply to Client 0: MSG 1
服务器正在端口7上运行
客户端0已连接
服务器正在端口7上运行
客户端0已发送:消息0
服务器对客户端0的答复:消息0
客户端1已连接
服务器正在端口7上运行
java.net.BindException:地址已在使用中:无法绑定
客户端0已发送:msg 1因此,在RequestProcessing.run
中,您决定忽略构造函数接收到的套接字,并在与正在侦听的端口相同的端口上打开DatagramSocket。你以为会发生什么事
class RequestProcessing extends Thread {
Socket channel;
int soHieuClient;
public RequestProcessing(Socket s, int i) {
// *****************
// The processor should be using this socket to communicate
// with a connected client *using TCP Streams*
channel = s;
clientNo = i;
}
public void run() {
try {
byte[] buffer = new byte[6000];
// *****************************
// But, instead of using the this.channel, your code
// decides to ignore the TCP socket,
// then open another UDP *"server-side like"* socket.
// First time it's OK, but the second thread attempting
// to open another DatagramSocket on the same port will fail.
// It's like attempting to open two TCP ServerSockets on the
// same port
DatagramSocket ds = new DatagramSocket(7);
[额外]
您需要决定要使用什么协议:如果您使用ServerSocket
/Socket
对,那么您可能需要TCP通信,因此不需要DatagramSocket
s
如果您想要UDP通信,那么服务器套接字
/套接字
与您的方法几乎没有关系,您需要使用数据报套接字
。构建它:
-而且只做一次李>
然后用服务器地址和端口限定每个数据包李>
请参阅Oracle网站上的教程 每次在main
服务器套接字上接收到新的客户端TCP连接时,都会启动RequestProcessing类的另一个实例。第一次启动RequestProcessing实例线程时,它成功绑定到UDP端口7。但是,第二个客户端连接,您尝试启动另一个RequestProcessing实例,而另一个实例已经存在。那是行不通的
您可能应该修改您的协议,这样RequestProcessing类每次都会选择一个新端口,并向TCP套接字发回所选端口的信号
但如果是我,我会这么做。为所有客户端提供一个RequestProcessing实例。假设您的UDP echo套接字只是将响应发送回数据包到达的地址,您只需要此类的一个实例。TCP解决方案:
实用程序类(我懒得在多个地方编写相同的代码):
服务器代码-不再有数据报,只使用来自套接字的输入/输出流,使用实用程序包装为读/写器
public class TCPServer
implements Runnable // in case you want to run the server on a separate thread
{
ServerSocket listenOnThis;
public TCPServer(int port)
throws IOException {
this.listenOnThis=new ServerSocket(port);
}
@Override
public void run() {
int client=0;
while(true) {
try {
Socket clientConn=this.listenOnThis.accept();
RequestProcessing processor=new RequestProcessing(clientConn, client++);
processor.start();
} catch (IOException e) {
break;
}
}
}
static public void main(String args[]) {
// port to be provided as the first CLI option
TCPServer server=new TCPServer(Integer.valueOf(args[0]));
server.run(); // or spawn it on another thread
}
}
class RequestProcessing extends Thread {
Socket channel;
int clientNo;
public RequestProcessing(Socket s, int i) {
channel = s;
clientNo = i;
}
public void run() {
try {
SocketRW utility=new SocketRW(this.channel);
while (true) {
String theString=utility.readLine().trim();
System.out.println("Client " + clientNo
+ " sent: " + theString);
if ("quit".equals(theString)) {
System.out.println("Client " + clientNo
+ " disconnected");
this.channel.close();
break;
}
theString = theString.toUpperCase();
utility.println(theString);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
客户端代码-不再使用数据报套接字,使用套接字的相同IO流
class TCPClient
implements Runnable // just in case you want to run multithreaded clients
{
Socket socket;
public TCPClient(InetAddress serverAddr, int port)
throws IOException {
this.socket=new Socket(serverAddr, port);
}
public void run() {
String theString="";
InputStreamReader isr = new InputStreamReader(System.in);
try {
SocketRW utility=new SocketRW(this.socket);
BufferedReader br = new BufferedReader(isr);
do {
System.out.print("Enter message: ");
theString = br.readLine().trim();
utility.println(theString);
System.out.println("Sent to server server: " + theString);
String received=utility.readLine();
System.out.println("Server reply: "+received);
} while (!"quit".equals(theString));
}
catch(IOException e) {
e.printStackTrace();
}
}
static public void main(String[] args) {
int port=Integer.valueOf(args[0]); // will throw if its no OK.
TCPClient client=new TCPClient(
InetAddress.getByName("192.168.109.128"),
port
);
client.run();
}
}
TCP端口与UDP端口是分开的。他的问题在于,他一直试图在每个客户端连接上绑定到UDP端口7。您的代码没有意义。您根本不需要TCP部分,也不需要服务器上的多个UDP套接字。
class TCPClient
implements Runnable // just in case you want to run multithreaded clients
{
Socket socket;
public TCPClient(InetAddress serverAddr, int port)
throws IOException {
this.socket=new Socket(serverAddr, port);
}
public void run() {
String theString="";
InputStreamReader isr = new InputStreamReader(System.in);
try {
SocketRW utility=new SocketRW(this.socket);
BufferedReader br = new BufferedReader(isr);
do {
System.out.print("Enter message: ");
theString = br.readLine().trim();
utility.println(theString);
System.out.println("Sent to server server: " + theString);
String received=utility.readLine();
System.out.println("Server reply: "+received);
} while (!"quit".equals(theString));
}
catch(IOException e) {
e.printStackTrace();
}
}
static public void main(String[] args) {
int port=Integer.valueOf(args[0]); // will throw if its no OK.
TCPClient client=new TCPClient(
InetAddress.getByName("192.168.109.128"),
port
);
client.run();
}
}