当我在发送一条指令后关闭客户端时,代码工作正常。但是当我希望客户端和服务器连接保持不变时,客户端可以一个接一个地向服务器发送多个指令,我在服务器上得到一个Null指针异常,在客户端得到消息java.net.SocketException: Socket is closed
。这在客户端将文件发送到服务器并且服务器成功接收到它之后发生。需要帮忙。错误发生在连接类代码行switch(clientMsg)
。在我看来,由于某种原因BufferedReader
in
会null
,但我可能会对此感到错误。代码如下。感谢。
服务器
public class server {
private static ServerSocket serverSocket;
private static Socket socket = null;
public static void print(Object s) {
System.out.println(s);
}
@SuppressWarnings("resource")
public static void main (String args[]) throws IOException {
System.out.print("Specify listening port: ");
Scanner _a = new Scanner(System.in);
int a = _a.nextInt();
try{
serverSocket = new ServerSocket(a);
}
catch(IOException e) {
System.out.println(e);
}
while (true) {
try {
socket = serverSocket.accept();
print("Connected to " + socket);
Thread client = new Thread(new Connection(socket));
client.start();
}
catch (IOException e) {
print(e);
}
}
}
}
连接
public class Connection implements Runnable {
public static void print(Object s) {
System.out.println(s);
}
private Socket socket;
private BufferedReader in = null;
public Connection(Socket client) {
this.socket = client;
}
@Override
public void run(){
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String clientMsg;
while (true) {
clientMsg = in.readLine();
switch (clientMsg) {
case "1":
receiveFile(); //method code not included
break;
default:
print("Command not recognized");
break;
}
//in.close();
}
}//try run()
catch (IOException e) {
print(e);
}
}
客户
public class client {
private static Socket connectToServer;
private static String fileName;
private static BufferedReader keybrdIn;
private static PrintStream msgToServer;
public static void println(Object e) {
System.out.println(e);
}
public static void print(Object e) {
System.out.print(e);
}
public static void main(String args[]) throws IOException{
try{
print("Enter IP: ");
String ip = new Scanner(System.in).nextLine();
print("Enter port: ");
int port = new Scanner(System.in).nextInt();
connectToServer = new Socket(ip, port);
keybrdIn = new BufferedReader(new InputStreamReader(System.in));
}catch(IOException e) {
println(e);
}
msgToServer = new PrintStream(connectToServer.getOutputStream());
while (true) {
try {
switch(Integer.parseInt(action())) { //action() method code not included
case 1:
msgToServer.println("1");
sendFile();
break;
default:
println("Invalid input");
break;
}
}catch (IOException e) {
println(e);
}
}
}
的sendfile()
public static void sendFile() throws IOException {
print("Enter file name: ");
fileName = keybrdIn.readLine();
File file = new File(fileName);
byte[] bytearray = new byte[8192];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = connectToServer.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
int count;
while ((count = dis.read(bytearray)) > 0){
dos.write(bytearray, 0, count);
}
dis.close();
dos.flush();
dos.close();
}
receiveFile()
public void receiveFile() {
try {
int count;
DataInputStream clientFileStream = new DataInputStream(socket.getInputStream());
String fileName = clientFileStream.readUTF();
OutputStream fileOutput = new FileOutputStream("_" + fileName);
byte[] mybytearray = new byte[8192];
BufferedOutputStream bos = new BufferedOutputStream(fileOutput);
System.out.println("Downloading " + fileName + " ...");
//outToClient().writeBytes("Uploading. Please wait...\n");
while ((count = clientFileStream.read(mybytearray)) > 0){
bos.write(mybytearray, 0, count);
}
fileOutput.close();
bos.close();
clientFileStream.close();
}
catch (IOException e) {
print(e);
}
}
答案 0 :(得分:1)
在sendFile()中,关闭数据输出流,关闭底层连接的输出流。
根据Socket.getOutputStream()的文档:
“关闭返回的OutputStream将关闭相关的套接字”。
答案 1 :(得分:1)
由于您已经关闭了流,它也将关闭套接字以及Eyal提到的。但是,在关闭流时,服务器端将知道这一点并返回-1以获取read()结果。 因此,即使您没有在开始时指定文件长度,这通常也能正常工作。
但是,由于您已经关闭了流,因此无论如何都无法重用它。要解决此问题,可能需要更改Client类,以便Client应创建套接字连接,发送文件,关闭套接字。这是打开的客户端套接字的一个生命周期。
或者也许在Client类的while循环中,1)取ip,port和filename发送2)创建新的Thread并提供这些信息让线程打开连接,发送文件,关闭连接3)同时, client while()可以保持从用户发送下一个ip,port和filename。通过这样做,您无需使客户端程序等待文件传输完成。
答案 2 :(得分:0)
关于服务器中的NPE,readLine()在流结束时返回null。你忽略了它。你应该在调用之后立即测试它,如果null关闭套接字并退出读循环。