Java 简单客户端-服务器应用程序-套接字问题
我正在使用TCP套接字编写一个简单的客户机-服务器应用程序。它使用多线程原理,允许多个客户端连接到同一台服务器 我在找出套接字中的一些错误时遇到了一些困难,您可能会告诉我,我在这个环境中是相当新的 我将向您展示我拥有的代码以及从中获得的输出,但基本上问题在于客户机与服务器的连接,我浏览了所有代码,但仍然找不到问题所在 服务器:Java 简单客户端-服务器应用程序-套接字问题,java,sockets,client-server,Java,Sockets,Client Server,我正在使用TCP套接字编写一个简单的客户机-服务器应用程序。它使用多线程原理,允许多个客户端连接到同一台服务器 我在找出套接字中的一些错误时遇到了一些困难,您可能会告诉我,我在这个环境中是相当新的 我将向您展示我拥有的代码以及从中获得的输出,但基本上问题在于客户机与服务器的连接,我浏览了所有代码,但仍然找不到问题所在 服务器: public static ArrayList<String> userList = new ArrayList<String>(); publi
public static ArrayList<String> userList = new ArrayList<String>();
public static int index;
public static String date;
public static void main(String args[]) throws Exception {//inicio main
ServerSocket server = new ServerSocket(6500); //Create socket on port 6500
System.out.println ("Server started on port 6500");
while (true){ //Waiting for clients
System.out.println("Server waiting for client connections..");
Socket socket = null;
BufferedReader reader = new BufferedReader(new FileReader("C:\\UNIV\\Redes\\workspace\\Copy of Ex_4.3_Teste\\lists\\blacklist.txt"));
String line = null;
socket = server.accept();
// Blacklist verification
while ((line = reader.readLine()) != null) {
if (line.equals(socket.getInetAddress().toString())) {
System.out.println("IP Blacklisted: " + socket.getInetAddress().toString());
System.out.println("Closing connection to " + socket.getInetAddress().toString());
PrintStream checkBlack = new PrintStream(socket.getOutputStream(),true);
checkBlack.println("***BLACKLISTED***");
reader.close();
checkBlack.close();
socket.close();
break;
}
}//End of Blacklist Verification
//Sending feedback in case of approved client
try {
PrintStream checkBlack = new PrintStream(socket.getOutputStream(),true);
checkBlack.println("***NBLACKLISTED***");
checkBlack.close();
} catch (SocketException e) {
}
userList.add(socket.getInetAddress().toString()); //Add connected user's IP to USERLIST
System.out.println("New connection..");
System.out.println("Size of UserList: " + userList.size());
Thread t = new Thread(new EchoClientThread(socket));
t.start(); //Starting Client Thread
}//End of Waiting for Clients
}//End of Main
public static class EchoClientThread implements Runnable{
private Socket s;
public EchoClientThread(Socket socket) {
this.s = socket;
}
public void run() {
String threadName = Thread.currentThread().getName(); //Thread Name
String stringClient = s.getInetAddress().toString(); //Client IP
System.out.println("Connected to " + stringClient);
try{
BufferedReader input = new BufferedReader(
new InputStreamReader(s.getInputStream()));
PrintStream output = new PrintStream(
s.getOutputStream(),true);
String line;
while ((line = input.readLine()) !=null) { //Input Cycle
System.out.println (stringClient+": "+threadName+": "+line); //Print command from client
if (line.equalsIgnoreCase("9")){ //Exit
break;
}
else if (line.equalsIgnoreCase("1")){ //Send List of Online Users
System.out.println("Option 1: Sending list of online users to " + stringClient);
output.println(" ");
output.println("List of Online Users:");
output.println(" ");
for(int i=0;i<userList.size();i++){
output.println(userList.get(i));
}
}
else if (line.equalsIgnoreCase("2")) { //Send message to a single user
System.out.println("Nothing here yet..");
}
else if (line.equalsIgnoreCase("3")) { //Send message to all the online users
System.out.println("Nothing here yet..");
}
else if (line.equalsIgnoreCase("4")){ //Send User Blacklist
System.out.println("Option 4: Sending user blacklist to " + stringClient);
BufferedReader reader = new BufferedReader(new FileReader("C:\\UNIV\\Redes\\workspace\\Copy of Ex_4.3_Teste\\lists\\blacklist.txt"));
String lineRead = null;
output.println(" ");
output.println("User Blacklist:");
output.println(" ");
while ((lineRead = reader.readLine()) != null) {
output.println(lineRead);
}
reader.close();
}
else{
output.println("Unknown command.");
}
output.println("***CLOSE***"); //Closes client's input cycle
output.println("***NBLACKLISTED***"); //Sending feedback in case of approved client
}//Input Cycle End
output.println("See you later!");
input.close(); //Closes inputStream
output.close(); //Closes outputStream
s.close(); //Closes Socket
}
catch (Exception e){
System.err.println("Server Side Error!");
System.out.println(e);
}
userList.remove(s.getInetAddress().toString());
System.out.println("Client "+ stringClient+" was disconnected!");
}//End of run()
}//End of EchoClientThread
}//End of EchoServerThread
但只要我尝试与客户联系,就会发生以下情况:
服务器端:
Server started on port 6500
Server waiting for client connections..
New connection..
Size of UserList: 1
Server waiting for client connections..
Connected to /127.0.0.1
java.net.SocketException: Socket is closed
Server Side Error!
Client /127.0.0.1 was disconnected!
但在客户端,它仍然显示输入菜单和命令提示符,如下所示:
CLIENT MENU
1 - List on-line users
2 - Send message to a single user
3 - Send message to all on-line users
4 - List Blacklisted Users
9 - Exit
127.0.0.1:6500#>
当我在客户端提示符上输入内容时,我得到:
127.0.0.1:6500#>1
Client Side Error!
java.net.SocketException: Software caused connection abort: recv failed
Connection Terminated
我知道错误的意思,套接字关闭了
几乎是不言自明的,但我就是找不到导致套接字关闭的代码问题
非常感谢您的帮助。您的黑名单机制不太正确 当您关闭与套接字关联的流时,它也将关闭套接字 所以服务器关闭它获得的任何套接字,然后将其交给线程, 尝试使用套接字但失败
// Blacklist verification
while ((line = reader.readLine()) != null) {
// blah blah blah
}//End of Blacklist Verification
//Sending feedback in case of approved client
try {
PrintStream checkBlack = new PrintStream(socket.getOutputStream(),true);
checkBlack.println("***NBLACKLISTED***");
checkBlack.close(); // <== why are you closing the stream?
} catch (SocketException e) {
}
调试器是你的朋友。你试过调试服务器代码吗?在我看来,您的服务器只是因为异常而关闭了套接字。如果您也可以发布异常,那么我得到的唯一异常是
java.net.SocketException:Socket在客户端尝试连接到服务器时关闭。但调试并没有帮到我,这也是我在这里问这个问题的部分原因。显然,它在System.out.println(“连接到”+stringClient)
之后立即关闭套接字,但我不知道为什么。我想我需要关闭流,以便为命令输入打开一个新的流。好吧,我想那不是。每天都是学习日^^非常感谢。PrintStream将SocketStream包裹起来,这样您就可以挂起它了。除非希望基础流关闭,否则不要关闭。流可能会变得混乱,有些你必须关闭其他你必须离开的流。哦,我明白了,执行socket.getOutputStream().write()
只写它必须写入的内容,然后关闭流而不关闭套接字?不,流保持打开状态。创建套接字时,您将创建一个上游(out)和一个下游(in)。每个插座只能有一个,因此它们需要在插座的使用寿命内保持打开状态。当您需要发送或接收某些内容时,您只需获得适当的流并进行读写。无论何时在套接字上调用get***Stream,您都会得到***的相同流,如果有多个线程使用同一套接字,这一点很重要。当套接字关闭时,流将为您清理。这有点令人困惑,但我想我现在明白了,感谢您花时间:)
127.0.0.1:6500#>1
Client Side Error!
java.net.SocketException: Software caused connection abort: recv failed
Connection Terminated
// Blacklist verification
while ((line = reader.readLine()) != null) {
// blah blah blah
}//End of Blacklist Verification
//Sending feedback in case of approved client
try {
PrintStream checkBlack = new PrintStream(socket.getOutputStream(),true);
checkBlack.println("***NBLACKLISTED***");
checkBlack.close(); // <== why are you closing the stream?
} catch (SocketException e) {
}
// Blacklist verification
while ((line = reader.readLine()) != null) {
// blah blah blah
}//End of Blacklist Verification
//Sending feedback in case of approved client
try {
socket.getOutputStream().write("***NBLACKLISTED***\n".getBytes());
} catch (SocketException e) {
e.printStackTrace();
}