我正在尝试使用Java套接字程序。在这里,客户端发送一个字符串,该字符串应由服务器反转并发送回客户端。服务器是多线程服务器。这是客户端代码:
import java.io.*;
import java.net.*;
class ClientSystem
{
public static void main(String[] args)
{
String hostname = "127.0.0.1";
int port = 1234;
Socket clientsocket = null;
DataOutputStream output =null;
BufferedReader input = null;
try
{
clientsocket = new Socket(hostname,port);
output = new DataOutputStream(clientsocket.getOutputStream());
input = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
}
catch(Exception e)
{
System.out.println("Error occured"+e);
}
try
{
while(true)
{
System.out.println("Enter input string ('exit' to terminate connection): ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputstring = br.readLine();
output.writeBytes(inputstring+"\n");
//int n = Integer.parseInt(inputstring);
if(inputstring.equals("exit"))
break;
String response = input.readLine();
System.out.println("Reversed string is: "+response);
output.close();
input.close();
clientsocket.close();
}
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
这是服务器端代码:
import java.io.*;
import java.net.*;
public class ServerSystem
{
ServerSocket server = null;
Socket clientsocket = null;
int numOfConnections = 0, port;
public ServerSystem(int port)
{
this.port = port;
}
public static void main(String[] args)
{
int port = 1234;
ServerSystem ss = new ServerSystem(port);
ss.startServer();
}
public void startServer()
{
try
{
server = new ServerSocket(port);
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
System.out.println("Server has started. Ready to accept connections.");
while(true)
{
try
{
clientsocket = server.accept();
numOfConnections++;
ServerConnection sc = new ServerConnection(clientsocket, numOfConnections, this);
new Thread(sc).start();
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
public void stopServer()
{
System.out.println("Terminating connection");
System.exit(0);
}
}
class ServerConnection extends Thread
{
BufferedReader br;
PrintStream ps;
Socket clientsocket;
int id;
ServerSystem ss;
public ServerConnection(Socket clientsocket, int numOfConnections, ServerSystem ss)
{
this.clientsocket = clientsocket;
id = numOfConnections;
this.ss = ss;
System.out.println("Connection "+id+" established with "+clientsocket);
try
{
br = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
ps = new PrintStream(clientsocket.getOutputStream());
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
public void run()
{
String line, reversedstring = "";
try
{
boolean stopserver = false;
while(true)
{
line = br.readLine();
System.out.println("Received string: "+line+" from connection "+id);
//long n = Long.parseLong(line.trim());
if(line.equals("exit"))
{
stopserver = true;
break;
}
else
{
int len = line.length();
for (int i=len-1; i>=0; i--)
reversedstring = reversedstring + line.charAt(i);
ps.println(""+reversedstring);
}
}
System.out.println("Connection "+id+" is closed.");
br.close();
ps.close();
clientsocket.close();
if(stopserver)
ss.stopServer();
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
当我输入字符串时,我在服务器端代码上遇到java.lang.NullPointerException,当我尝试重新输入字符串时,我得到一个java.net.SocketException:Socket关闭异常。
客户端输出:
Enter input string ('exit' to terminate connection):
usa
Reversed string is: asu
Enter input string ('exit' to terminate connection):
usa
Error occured.java.net.SocketException: Socket closed
服务器端输出:
Server has started. Ready to accept connections.
Connection 1 established with Socket[addr=/127.0.0.1,port=3272,localport=1234]
Received string: usa from connection 1
Received string: null from connection 1
Error occured.java.lang.NullPointerException
我尝试了很多但是我没有得到这些例外的地方。有人可以帮我从这里出去吗?先感谢您! :)
答案 0 :(得分:1)
这3行是客户端代码中的罪魁祸首:
output.close();
input.close();
clientsocket.close();
将它们放在while循环之外,并在finally块中:
try {
while(true) {
// client code here
}
} catch (Exception e) {
e.printStackTrace(); // notice this line. Will save you a lot of time!
} finally {
output.close(); //close resources here!
input.close();
clientsocket.close();
}
问题是,就像它最初一样,你关闭了所有资源,但在下一次迭代中,你想要使用它们,而不是初始化它们......
正确处理异常,包括正确记录异常。始终使用log4j
LOG.error("Unexpected error when deionizing the flux capacitor",e);
或printStackTrace()
方法
e.printStackTrace();
如果您发布了堆栈跟踪,请不要忘记在代码中包含行号。
修改强>
对于相反的问题:
else
{
int len = line.length();
reversedString=""; //this line erases the previous content of the reversed string
for (int i=len-1; i>=0; i--) { //always use brackets!!!
reversedstring = reversedstring + line.charAt(i);
}
ps.println(""+reversedstring);
}
发生什么事了? reversString只是随着每次迭代而增长和增长,而不会被删除...这就是为什么我喜欢在我需要的最严格的范围内声明我的变量。
修改强>
要使退出命令不对服务器执行,这可以是一个(非常简单)的解决方案:
在ServerConnection类中:
while(true)
{
line = br.readLine();
System.out.println("Received string: "+line+" from connection "+id);
if(line.equals("exit"))
{
break; //just stop this connection, don't kill server
}
else if(line.equals("stop"))
{
stopserver = true; //stop server too
break;
}
else
{
int len = line.length();
for (int i=len-1; i>=0; i--) {
reversedstring = reversedstring + line.charAt(i);
}
ps.println(""+reversedstring);
}
}
这里发生了什么?有一个新的“命令”stop
,它使服务器停止,退出只是退出客户端,但不会停止服务器本身......
答案 1 :(得分:0)
在循环的第一次运行中,您将关闭导致问题的所有连接。 output.close(); input.close(); clientsocket.close();,将其向下移动
答案 2 :(得分:0)
您的服务器正在调用br.readLine();
它会等到客户端发送它,但是一旦发送了一个字符串,您就会调用:
output.close();
input.close();
clientsocket.close();
这将释放资源并导致br.readLine()
成为null
if (line.equals("exit")) {
此行为空,因此您无法调用等号。
if ("exit".equals(line)) {
您可以像这样更改它以防止此异常。
将close语句移动到finally块,即使在服务器中也是如此,如果你在while中有异常,则永远不会达到关闭,这可能会导致内存泄漏。
客户端:
} finally {
output.close();
input.close();
clientsocket.close();
}
服务器:
} finally {
br.close();
ps.close();
clientsocket.close();
}
注意:您可以在关闭之前验证它们,以确保它们不为空。
你可能必须提供输入为null的情况,或者退出循环,通常你会使用这样的东西:
if (null==line || "exit".equals(line)) {
如果客户端发送null,则表示出错。