获得;错误:java.net.SocketException:Socket已关闭;尝试将消息从客户端类发送到服务器类时

获得;错误:java.net.SocketException:Socket已关闭;尝试将消息从客户端类发送到服务器类时,java,sockets,client,server,Java,Sockets,Client,Server,我不明白为什么。当服务器向客户机发送字符串时,客户机可以很好地得到它。但是,当我向客户机类添加代码以向服务器发送字符串时,它不起作用。帮忙 编辑:所以我删除了out.close();并将其替换为skt.shutdownOutput();但现在,当我给我的班级打电话时,我得到: ====================== Server has connected! Server: Sending message: Test string to show connection between se

我不明白为什么。当服务器向客户机发送字符串时,客户机可以很好地得到它。但是,当我向客户机类添加代码以向服务器发送字符串时,它不起作用。帮忙

编辑:所以我删除了out.close();并将其替换为skt.shutdownOutput();但现在,当我给我的班级打电话时,我得到:

======================
Server has connected!
Server: Sending message: Test string to show connection between server and client.
Client: Received message: null
Server: Received message: null
为什么?

客户端类:

import java.lang.*;
import java.io.*;
import java.net.*;

class Client {

public static void main(String args[]) {

}

//for receiving messages from Server

public void receiveMessage() {
    try {
        Socket skt = new Socket(InetAddress.getLocalHost().getHostName(), 1234);
        BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
        //while (!in.ready()) {}
        System.out.println("Client: Received message: " + in.readLine()); // Read one line and output it
        in.close();
        //skt.close(); //maybe delete
    } catch (Exception e) {
        System.out.print("Client had error receiving message.\n");
    }
}

//for sending messages to Server
public void sendMessage(String message) throws IOException {
    try {
        Socket skt = new Socket(InetAddress.getLocalHost().getHostName(), 1234);
        PrintWriter pw = new PrintWriter(skt.getOutputStream());
        System.out.println("Client: Sending message: " + message);
        pw.print(message);
        //skt.close(); //maybe delete
    } catch (Exception e) {
        System.out.println(e);
        System.out.print("Client had error sending message.\n");
    }

}
}
服务器类:

import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Server {

String message = "Test string to show connection between server and client.";

public void Open() {
    final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
    Runnable serverTask = new Runnable() {

        @Override
        public void run() {
            try {
                System.out.println("Opening...");
                ServerSocket srvr = new ServerSocket(1234);
                while (true) {
                    Socket skt = srvr.accept();
                    clientProcessingPool.submit(new ClientTask(skt));
                }
            } catch (Exception e) {
                System.out.println(e);
                System.out.print("You're opening too many servers in the same location, fool!\n");
            }
        }
    };
    Thread serverThread = new Thread(serverTask);
    serverThread.start();
}

private class ClientTask implements Runnable {

    private final Socket skt;

    private ClientTask(Socket skt) {
        this.skt = skt;
    }

    @Override
    public void run() {
        //for sending messages
        System.out.println("======================");
        System.out.println("Server has connected!");
        PrintWriter out = null;
        try {
            out = new PrintWriter(skt.getOutputStream(), true);
        } catch (IOException ex) {
            System.out.println(ex);
            System.out.println("Server had error sending message.");
        }
        System.out.print("Server: Sending message: " + message + "\n");
        out.print(message);
        //out.close();
        try {
            skt.shutdownOutput();
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }

        /*
        try {
            skt.close();
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }*/

        //for receiving messages
        //maybe make message procesing method
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(skt.getInputStream()));
            System.out.println("Server: Received message: " + br.readLine()); // Read one line and output it
            //br.close();
            //skt.close(); //maybe delete
        } catch (Exception e) {
            System.out.println("Server had error receiving message.");
            System.out.println("Error: " + e);
        }

    }
}
}

谢谢你的建议

    out.print(message);
    out.close();
关闭
PrintStream
即关闭底层
OutputStream

Socket
中的
getOutputStream()
文档说明:

关闭返回的
OutputStream
将关闭关联的套接字

因此,当您关闭
打印流时,您也会关闭套接字。仅当完成当前会话的客户端和服务器之间的所有通信时,才关闭流


编辑后的下一个问题是没有刷新数据。客户端连接时,服务器打印,而不刷新,因此数据仍在缓冲区中等待,而不是在流中等待。像以前那样关闭流也会刷新数据,但现在您只是将流丢弃,未刷新的数据将被丢弃

因此,流关闭,客户端看到指示流结束的
null

因此,您需要在丢弃流之前刷新数据

服务器报告它已收到
null
,因为在其输入流中没有向它发送任何内容。客户机收到信息后退出,这导致套接字关闭,流关闭,服务器看到流结束

如果调用
sendMessage
方法,您将看到几乎相同的结果。溪流正在写东西,但没有人在听。由于消息很短,服务器不会阻止写入消息,但是没有人在另一端读取消息,因此可能会阻止写入消息。然后,服务器尝试读取发送给它的内容。但是您的客户端在完成执行并关闭套接字之前不会刷新数据。因此,服务器也会看到
null

关闭
PrintStream
即关闭底层
OutputStream

Socket
中的
getOutputStream()
文档说明:

关闭返回的
OutputStream
将关闭关联的套接字

因此,当您关闭
打印流时,您也会关闭套接字。仅当完成当前会话的客户端和服务器之间的所有通信时,才关闭流


编辑后的下一个问题是没有刷新数据。客户端连接时,服务器打印,而不刷新,因此数据仍在缓冲区中等待,而不是在流中等待。像以前那样关闭流也会刷新数据,但现在您只是将流丢弃,未刷新的数据将被丢弃

因此,流关闭,客户端看到指示流结束的
null

因此,您需要在丢弃流之前刷新数据

服务器报告它已收到
null
,因为在其输入流中没有向它发送任何内容。客户机收到信息后退出,这导致套接字关闭,流关闭,服务器看到流结束

如果调用
sendMessage
方法,您将看到几乎相同的结果。溪流正在写东西,但没有人在听。由于消息很短,服务器不会阻止写入消息,但是没有人在另一端读取消息,因此可能会阻止写入消息。然后,服务器尝试读取发送给它的内容。但是您的客户端在完成执行并关闭套接字之前不会刷新数据。因此,服务器也会看到
null

关闭
PrintStream
即关闭底层
OutputStream

Socket
中的
getOutputStream()
文档说明:

关闭返回的
OutputStream
将关闭关联的套接字

因此,当您关闭
打印流时,您也会关闭套接字。仅当完成当前会话的客户端和服务器之间的所有通信时,才关闭流


编辑后的下一个问题是没有刷新数据。客户端连接时,服务器打印,而不刷新,因此数据仍在缓冲区中等待,而不是在流中等待。像以前那样关闭流也会刷新数据,但现在您只是将流丢弃,未刷新的数据将被丢弃

因此,流关闭,客户端看到指示流结束的
null

因此,您需要在丢弃流之前刷新数据

服务器报告它已收到
null
,因为在其输入流中没有向它发送任何内容。客户机收到信息后退出,这导致套接字关闭,流关闭,服务器看到流结束

如果调用
sendMessage
方法,您将看到几乎相同的结果。溪流正在写东西,但没有人在听。由于消息很短,服务器不会阻止写入消息,但是没有人在另一端读取消息,因此可能会阻止写入消息。然后,服务器尝试读取发送给它的内容。但是您的客户端在完成执行并关闭套接字之前不会刷新数据。因此,服务器也将看到