Socket中InputStream的read方法的阻塞特性

用java,搞通信一定会接触到Socket,ServerSocket这2个类,基本使用非常简单,但如果想良好的控制,还是得小心之非常啊.因为Socket中InputStream的read()当管道无数据时便等待数据的填充,但OutputStream可以继续写入数据.如果这点搞清楚了,就没多大的问题了, 
read()阻塞后,继续想服务器提交数据,read()方法便会读出服务器的响应数据来. 
此次便是记录下,如何比较随心的使用java的Socket. 
2个类, 

TCPServer 

package org.sk.lib.socket;  
  
import java.io.IOException;  
import java.io.PrintStream;  
import java.net.ServerSocket;  
import java.net.Socket;  
import java.util.Scanner;  
  
public class TCPServer {  
    private ServerSocket server;  
    private Socket client;  
      
    public TCPServer(int port) throws IOException {  
        // TODO Auto-generated constructor stub  
        server = new ServerSocket(port);  
    }  
    /** 
     * 开始tcp的服务 
     * @throws IOException 
     */  
    public void start() throws IOException{  
        while(true){  
            client = server.accept();  
            new Thread(new ClientThread(client)).start();  
        }  
    }  
    public static void main(String[] args) throws IOException {  
        new TCPServer(1234).start();  
    }  
    /** 
     * 客户端处理 
     * @author Ozone 
     * 
     */  
    class ClientThread implements Runnable{  
        private Socket client;  
        private Scanner in;  
        private PrintStream out;  
          
        public ClientThread(Socket client) throws IOException {  
            // TODO Auto-generated constructor stub  
            this.client = client;  
            in = new Scanner(client.getInputStream());  
            out = new PrintStream(client.getOutputStream());  
        }  
        public void run() {  
            // TODO Auto-generated method stub  
            try {  
                blockProcess();  
            } catch (IOException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
        /*** 
         * 处理客户端的请求,一条一条的进行处理,每次接收1行指令,指令以\n为结束 
         * @throws IOException 
         */  
        private void blockProcess() throws IOException{  
            String line;  
            while(in.hasNextLine()){  
                line = in.nextLine();  
                if(line.equals("bye")){  
                    out.println("bye");  
                    break;  
                }  
                {  
                    //需要进行处理  
                    System.out.println(line);  
                    out.println("a\nb\nc\nd");  
                }  
            }  
            in.close();  
            out.close();  
            client.close();  
        }  
    }  
}  

TCPClient: 

package org.sk.lib.socket;  
  
import java.awt.BorderLayout;  
import java.awt.event.ActionEvent;  
import java.awt.event.ActionListener;  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.net.Socket;  
import java.net.UnknownHostException;  
import java.util.Scanner;  
  
import javax.swing.JButton;  
import javax.swing.JFrame;  
import javax.swing.JTextArea;  
  
  
public class TCPClient {  
      
    private Socket client;  
    private PrintWriter out;  
    private Scanner in;  
      
    public TCPClient(String addr, int port) throws UnknownHostException,  
            IOException {  
        client = new Socket(addr, port);  
        in = new Scanner(client.getInputStream());  
        out = new PrintWriter(client.getOutputStream(),true);  
    }  
    //初始化 一个窗体  
    public void initFrame() {  
        JFrame frame = new JFrame();  
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        frame.setSize(400, 300);  
        frame.setVisible(true);  
        final JTextArea ta = new JTextArea();  
        frame.add(ta, BorderLayout.NORTH);  
        JButton bt = new JButton("go");  
        frame.add(bt, BorderLayout.CENTER);  
        frame.pack();  
        bt.addActionListener(new ActionListener() {  
  
            public void actionPerformed(ActionEvent e) {  
                // TODO Auto-generated method stub  
                if(!ta.getText().equals(""))  
                    send(ta.getText());  
            }  
        });  
    }  
    /** 
     * 将数据发送至 输出流 
     * @param cont 
     */  
    private void send(String cont){  
        out.println(cont);  
    }  
    /*** 
     * 处理客户端的读取操作 
     * 1 当管道内无数据(服务器无响应)便阻塞. 
     * 2 管道内有多行数据,便一直读取到完, 
     * 1,2 循环,直到收到服务器的bye字符,连接关闭,会话结束 
     * @throws IOException 
     */  
    public void registerListener() throws IOException {  
        String line;  
        while (in.hasNextLine()) {  
            line = in.nextLine();  
            if(line.equals("bye")){  
                break;  
            }  
            //处理服务器响应  
            System.out.println(line);  
        }  
        in.close();  
        out.close();  
        client.close();  
        System.out.println("连接关闭");  
    }  
  
    public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {  
        TCPClient client = new TCPClient("127.0.0.1",1234);  
        client.initFrame();  
        client.registerListener();  
    }  
}  

启动TCPServer,之后运行TCPClicent,在小窗口中输入字符,bye退出.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
InputStreamread()方法是一个阻塞方法,当没有可读取的数据时,调用该方法会一直阻塞直到有数据可读取或者发生异常。 如果在Server端的inputStream.read()方法遇到阻塞的问题,可能是因为客户端的outputStream没有关闭。这样会导致Server端一直等待数据而无法继续执行下去。因此,有两种解决方案可以尝试。 一种解决方案是在客户端发送完消息后调用socket的shutdownOutput()方法,关闭outputStream。这样可以告知Server端数据发送完毕,从而避免阻塞问题的发生。 另一种解决方案是在客户端发送完消息后关闭socket的输出流(outputStream),即调用outputStream的close()方法。这样也能解决Server端的阻塞问题。 需要注意的是,在关闭outputStream之后还需要继续使用客户端的inputStream来获取Server端的回复消息,因此在关闭outputStream之前不能关闭socket或者inputStream。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [通过Socket读取数据InputStream.read()阻塞问题](https://blog.csdn.net/echohawk/article/details/124668763)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值