记录 serverSocket socket 输入,输出流,关闭顺序,阻塞,PrintWriter的一些问题.

关于socket.getOutputStream() 的一些问题, OutputStream的flush是一个空方法,因此须要另外一个实现了Flush的流来包装一下服务器

这里为何使用PrintWriter,而不使用BufferedWritersocket

缘由是在接收方使用BufferedReader 的readLine,而BufferedWriter.write并不会自动换行,因此会致使读取阻塞,须要手动换行,代码以下:测试

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("你好啊");
//            由于在服务端使用的是readLine,因此若是不调用newLine,那么会一直阻塞
            bw.newLine();
            bw.flush();

 

 

如下两个测试类代码,在输出数据的时候,输出空行为结束符,在读取输入流的时候都在循环内判断了readLine长度是否为0(固然规范的作法是约定长度,根据长度判断是否结束),缘由以下摘抄☞:点击这里spa

对于socket,不能认为把某次写入到流中的数据读取完了就算流结尾了,可是socket流还存在,还能够继续往里面写入数据而后再读取。因此用BufferedReader封装socket的输入流,调用BufferedReader的readLine方法是不会返回null的.net

因此在循环内若是不判断   msg!=null&&msg.length()>0  那么程序将会一直阻塞在这里(程序是由于readLine阻塞,并非死循环)code

 

关于流的关闭会影响socket的使用,并且对一次链接关闭流之后,没有办法再次打开,哪怕只关闭输入流,也会致使输出流不能使用.反之亦然.server

因此若是在一次IO操做之后,还有另外一次IO,那么就先不关闭.等所有用完再关闭.blog

 

ServerSocket get

@RunWith(JUnit4.class)
public class ServerSocketTest {
    @Test
    public void testServer(){
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
//            serverSocket.setReuseAddress(true);
//            System.out.println(InetAddress.getLocalHost());//获取的本机地址不必定正确
            serverSocket.bind(new InetSocketAddress(8000));
            
            while(true){
                //一旦链接,返回的socket包含客户端信息的socket
                Socket socket = serverSocket.accept();
                PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
                pw.println("host:"+socket.getInetAddress()+":"+socket.getPort()+"创建连接");
                //这里发送空行做为结束符,固然规范作法是根据长度做为标识
                pw.println("");
                //由于new PrinWriter的时候指定了autoFlush的参数为true因此不用手动flush
//                pw.flush();
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){
                    System.out.println(msg);
                }
                pw.close();
                br.close();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    
}

 

 

ClientSocketit

/**
 * 
 * @author lzw
 *
 */
@RunWith(JUnit4.class)
public class SocketClient {
    @Test
    public void testClient() throws UnknownHostException, IOException{
        //表示链接到服务器的 地址以及端口
        SocketAddress address = new InetSocketAddress("19.95.103.112",8000);
        Socket socket = new Socket();
        socket.connect(address,60000);//链接
        //读取服务端返回的数据
        getMsb(socket);
        sendMsg(socket);
        socket.close();
    }
    
    
    private void sendMsg(Socket socket){
        PrintWriter pw = null;
//        BufferedWriter bw = null;
        try {
            
//            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//            bw.write("你好啊");
            //由于在服务端使用的是readLine,因此若是不调用newLine,那么会一直阻塞
//            bw.newLine();
//            bw.flush();
//            OutputStream os =  socket.getOutputStream();
//            //这个是一个空方法
//            os.flush();
            pw = new PrintWriter(socket.getOutputStream(),true);
            pw.println("你好啊");
       //输出空行做为结束标识
       pw.println("");
//由于new PrinWriter的时候指定了autoFlush的参数为true因此不用手动flush // pw.flush(); } catch (IOException e) { e.printStackTrace(); }finally{ //由于本次链接,到这个方法之后没有更多交互,因此能够关闭 if(pw!=null){ pw.close(); } } } private void getMsb(Socket socket){ InputStream is = null; BufferedReader br = null; try { is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){ System.out.println(msg+"--"); } } catch (IOException e) { e.printStackTrace(); }finally{ //这里不能关闭流,不然会把socket也关闭了(由于后面还要发送数据,因此不能关闭流,无论是关闭输入输入其中之一,都会致使输入和输出都不能使用) // try { // if(br!=null) // br.close(); // } catch (IOException e) { // e.printStackTrace(); // } } } }
相关文章
相关标签/搜索