2 m0 37741173 m0_37741173 于 2018.02.03 18:23 提问

JAVA中Socket对象如何重用多次?

试了一下,目前已知的 让socket发送流中的数据 只有一下三种方式

1.shutDown流
2.close流/close socket
3.sendUrgentData

前两种都会socket对象无法再次使用,如果想多次发送数据,只能用第3种。
有更优雅的方式实现socket重用吗?

4个回答

huruiba
huruiba   2018.02.03 20:23
已采纳

不是的,你得仔细了解一下socket的读写数据机制。
关闭writer和关闭socket的时候,**发现buffer有数据没有写出,会写一遍**,但不是必须关闭流和关闭socket**才会写数据**。
一般是通过输出流的 write()和flush()方法,完成写操作。
想要多次的输出数据,首要条件就是socket不被close和outputStream没有close...
顺便给你贴点代码

 public class TestSocket {

    public static void main(String[] args) throws IOException {
        int port = 10086;
        ServerSocket server = new ServerSocket(port);
        System.out.println("等待与客户端建立连接...");
        while (true) {
            Socket socket = server.accept();
            new Thread(new Task(socket)).start();

        }
        // server.close();
    }

    /**
     * 处理Socket请求的线程类
     */
    static class Task implements Runnable {

        private Socket socket;

        /**
         * 构造函数
         */
        public Task(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                handlerSocket();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * 跟客户端Socket进行通信
         * 
         * @throws IOException
         */
        private void handlerSocket() throws Exception {
            for (;;) {
                StringBuilder sb = new StringBuilder();
                InputStream inputStream = socket.getInputStream();
                String temp;
                int index;
                sb.append(inputStream.read());
                System.out.println("Form Cliect[port:" + socket.getPort() + "] 消息内容:" + sb.toString());
                // 回应客户端
                Writer writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
                writer.write(String.format("Hi", socket.getPort()));
                writer.flush();
//              writer.close();
//              socket.close();
            }
        }
    }
}

huruiba
huruiba 回复Light_0X0000: 不可以的,socket.getInputStream()是一个阻塞方法,只有读到数据,线程才会往下走。把socket放到list里,也没用的,第一个socket取不到inputstream的数据,就不会往下遍历了。socket和server这套api,在多客户端的时候,是基于一个线程一个socket的模式运行,也叫bio。你也可以去了解一下nio,换一套api,用socketchannel,bytebuffer,selector。这一套可以不用一个线程一个socket
4 个月之前 回复
m0_37741173
m0_37741173 谢谢了。如果把socket都存到一个集合里,用一个线程来遍历集合(而不是一个socket用一个线程),可行吗
4 个月之前 回复
devmiao
devmiao   Ds   Rxr 2018.02.03 23:25
 可以利用多线程, 服务器端不断接收客户端连接, 连接一个就开一个线程处理 客户端的交互,
这里有一个简单的例子,Client端发送消息给Server端,并读取Server端的回复信息;而Server端则先读取Client端的数据,再回复数据。
Server端:

 public class Main {
    public static void main(String[] args) {
        ServerSocket server;
        try {
            server = new ServerSocket(8800);
            System.out.println("Wait for connection...");
            Socket socket = server.accept();
            BufferedInputStream is = new BufferedInputStream(
                    socket.getInputStream());
            byte[] buff = new byte[1024];
            int size;
            while ((size = is.read(buff)) != -1) {
                System.out.println(new String(buff, 0, size));
            }

            OutputStream os = socket.getOutputStream();
            os.write("您好,我是Server端".getBytes());
            os.flush();
            os.close();
            System.out.println("ok,client send over.");
            server.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
Client端:

public class Client {
    public static void main(String[] args) throws Exception 
    {
        Socket s = new Socket("localhost",8800);
        OutputStream os = s.getOutputStream();
        os.write("您好,我是客户端".getBytes());
        os.close();

        InputStream in = s.getInputStream();
        byte[] buff = new byte[1024];
        BufferedInputStream is = new BufferedInputStream(in);
        int size;
        while((size = is.read(buff)) != -1){
            System.out.println(new String(buff,0,size));
        }
        System.out.println("over...");
        s.close();
    }
}
liu13816947142
liu13816947142   2018.02.03 21:24

可以一直发的,用printwriter
或者用bufferedwriter然后每条消息要加\r\n结尾并且调用flush

oyljerry
oyljerry   Ds   Rxr 2018.02.03 19:40

为什么要重用。你直接保持着socket对象。就可以一直发送数据

baidu_41706873
baidu_41706873 .你直接保持着socket对象,就行了。
4 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!