zoukankan      html  css  js  c++  java
  • 使用jdk的socket通信

    使用JDK提供的API进行网络通信,会用到Socket,ServerSocket两个类。写个简单的SERVER和CLIENT之间发消息的小程序,竟然发现了挺多的问题。

    这是服务器端代码:

    package org.chat;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    
    public class ChatServer {
    
    	public static void main(String[] args) {
    		ChatServer server = new ChatServer();
    		server.start();
    	}
    
    	public void start() {
    		while (true) {
    			ServerSocket s = null;
    			Socket socket = null;
    			try {
    				s = new ServerSocket(10001);
    				socket = s.accept();
    				
    				BufferedReader 	in 	= new BufferedReader(new InputStreamReader(socket.getInputStream()));
    				PrintWriter 	out = new PrintWriter(socket.getOutputStream(),true);
    	
    				String content = in.readLine();
    				System.out.println(content);
    				content = content + "1";
    				out.print(content);
    				out.flush(); // if not flush, client can't receive data
    				
    				in.close();
    				out.close();
    				
    			} catch (IOException e) {
    				e.printStackTrace();
    			} finally{
    				try {
    					s.close();
    					socket.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    }
    


    这是客户端代码:

    package org.chat;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class Client {
    	public static void main(String[] args) {
    		Socket socket = null;
    		try {
    			socket = new Socket("128.192.184.93", 10001);
    			
    			BufferedReader 	in 	= new BufferedReader(new InputStreamReader(socket.getInputStream()));
    			PrintWriter 	out = new PrintWriter(socket.getOutputStream(), true);
    			
    			out.println("hello");
    			
    			String reply = in.readLine();
    			System.out.println(reply);
    			
    			in.close();
    			out.close();
    			
    		} catch (UnknownHostException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally{
    			try {
    				socket.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    逻辑很简单:Client会向ChatServer发一个字符串"hello",ChatServer收到后,在这个字符串后面加1,然后发给Client。

    这其中遇到了几个问题:

    1.PrintWriter构造函数参数autoFlush设置

    PrintWriter的构造函数里的第二个参数autoFlush,API文档里解释是:if true, the println,printf, or format methods will flush the output buffer。注意不包括print。

    因此,对于ChatServer,32,33行(print),如果不调用flush,Client就收不到数据,尽管在PrintWriter的构造函数里,autoFlush=true;而Client的19行(println),无需调用flush,也能发送数据。

    2.Socket的InputStream和OutputStream有关联,如果一个在用,另一个不可关闭

    在ChatServer中,如果把35行代码in.close()放到29行之后,30行之前,也就是说,in在读取了数据之后,就关闭掉,造成的后果就是32行代码out.print()失效,这是因为in.close()使socket关闭了,Client只能收到一个null

    3.BufferReader的readLine()方法

    首先,改方法是阻塞的,如果读不到(即使读到null也算读到),就会阻塞。

    该方法会读取一行数据,就是说,读取第一个换行符之前的数据,如果发送的数据中没有换行符,那么,readLine可能会阻塞。

    PrintWriter.print()发送的数据中没有换行符,所以多次调用,接受方BufferReader.readLine()读到的数据包括了多次print的数据。


  • 相关阅读:
    [LeetCode] 875. Koko Eating Bananas 科科吃香蕉
    [LeetCode] 874. Walking Robot Simulation 走路机器人仿真
    [LeetCode] 995. Minimum Number of K Consecutive Bit Flips 连续K位翻转的最小次数
    [LeetCode] 873. Length of Longest Fibonacci Subsequence 最长的斐波那契序列长度
    [LeetCode] 872. Leaf-Similar Trees 叶结点相似的树
    [LeetCode] 870. Advantage Shuffle 优势洗牌
    [LeetCode] 869. Reordered Power of 2 重新排序为2的倍数
    [LeetCode] 868. Binary Gap 二进制间隙
    [LeetCode] 867. Transpose Matrix 转置矩阵
    [LeetCode] 866. Prime Palindrome 质数回文数
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3149455.html
Copyright © 2011-2022 走看看