Fuck i`m going out without you

Java Socket Server-Client模式 1.0

仅支持一问一答模式 , 由client先行发送消息 , 最后结束时由Client发出 “bye”。

收完才能发 , 发完才能收 收发无法同时进行

Server , Client类里用到了 读类型的 InputStreamReader , socket.getInputStream , BufferedReader() , System.in
以及 写类型的PrintWriter , socket.getOutputStream()。

 

 1 /*
 2     这是socket编程的第一个版本 , 仅能实现先由client端发一句话 , 
 3     然后在依次你一句我一句这样对话 , 结束方式是由client端发送bye。
 4     
 5     现在想到的改进方式是用多线程 , 每个端都设置一个接收 一个发送
 6     线程 , 互不干扰。
 7 
 8 
 9 */
10 package test;
11 
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStreamReader;
15 import java.io.PrintWriter;
16 import java.net.Socket;
17 import java.net.UnknownHostException;
18 
19 public class Client {
20     
21     
22     public void initial() throws IOException {
23         
24         try {
25             Socket socket = null;
26             socket = new Socket("127.0.0.1",4700);
27             BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
28             BufferedReader biServer = null;
29             PrintWriter pw = null;
30             pw = new PrintWriter(socket.getOutputStream());
31             biServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
32             String reply = null;
33             String message = bi.readLine();// 首先发声 , message获取键盘输入
34             while(!message.equals("bye") ) {
35 //                System.out.println(message);
36                 pw.println(message);//向Server发送message
37                 pw.flush();
38                 
39                 reply = biServer.readLine();//阻塞 , 等待Server消息
40                 System.out.println("Server: "+reply);
41                 
42                 message = bi.readLine();// 现在获取buffer中的信息 , 以回车为结束
43             }
44             
45             bi.close();
46             biServer.close();
47             pw.close();
48             socket.close();
49         } catch (UnknownHostException e) {
50 
51             e.printStackTrace();
52         } catch (IOException e) {
53 
54             e.printStackTrace();
55         }
56         
57     }
58     
59 
60     
61     public static void main(String[] args) {
62         Client client = new Client();
63         try {
64             client.initial();
65         } catch (IOException e) {
66 
67             e.printStackTrace();
68         }
69 
70     }
71 }

 1 /*
 2     这是socket编程的第一个版本 , 仅能实现先由client端发一句话 , 
 3     然后在依次你一句我一句这样对话 , 结束方式是由client端发送bye。
 4     
 5     现在想到的改进方式是用多线程 , 每个端都设置一个接收 一个发送
 6     线程 , 互不干扰。
 7 
 8 
 9 */
10 package test;
11 import java.io.BufferedReader;
12 import java.io.IOException;
13 import java.io.InputStreamReader;
14 import java.io.PrintWriter;
15 import java.net.*;
16 public class Server {
17     ServerSocket serverSocket = null;
18     public void initial() {
19         try {
20             this.serverSocket = new ServerSocket(4700);
21         }catch(Exception e) {
22             System.out.println("创建端口失败");
23         }
24         
25     }
26     
27     public void connect() {
28         Socket linkSocket = null;
29         try {
30             linkSocket = this.serverSocket.accept();
31         }catch(Exception e) {
32             System.out.println("erro! :"+e);
33         }
34         
35         try {
36             InputStreamReader isr = new InputStreamReader(linkSocket.getInputStream());
37             BufferedReader br = new BufferedReader(isr);
38             PrintWriter pw = new PrintWriter(linkSocket.getOutputStream());
39             BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
40             String message = br.readLine();//阻塞 , 等待client传消息
41             String reply = null;
42             while(!message.equals("bye")) {
43                 System.out.println("client: "+message);
44                 reply = bi.readLine();//接收到了Client的信息 , 现在获取buffer中的信息 , 以回车为结束
45                 pw.println(reply);  
46                 pw.flush();      //发送键盘输入的reply给client
47                 message = br.readLine();//继续等待client的信息
48                 
49             }
50             pw.close();
51             br.close();
52             
53         } catch (IOException e) {
54             // TODO Auto-generated catch block
55             e.printStackTrace();
56         }
57         
58         try {
59             linkSocket.close();
60         } catch (IOException e) {
61             // TODO Auto-generated catch block
62             e.printStackTrace();
63         }        
64     }
65     
66     public void close() {
67         try {
68             this.serverSocket.close();
69         } catch (IOException e) {
70             // TODO Auto-generated catch block
71             e.printStackTrace();
72         }
73     }
74     
75     public static void main(String[] args) {
76         Server server = new Server();
77         server.initial();
78         server.connect();
79         server.close();
80     }
81 }

 

以上代码写的非常乱 , 很粗糙 , try catch写的非常没有逻辑 , 不想整理了,此为我的1.0版本。


接下来写一写我的一些收获:

1.java中IO流的操作

  主要内容看收藏夹 , 本次主要使用了字符流 , BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );

用buffer 可以一次取一行用readLine() , 避免了用InputStreamReader的 read() , 循环取的麻烦。

   针对于此次试验 , 

      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

      String message = br.readLine();

这里会一直阻塞直到有输入 , 对于readLine()来说就是一点回车就从缓冲区拿走一句。

搜输入阻塞时的一个百度回答:

 

阻塞。。。
当前线程执行到需要输入时:
启动另一个线程接收数据(可能不是线程,总之是另一个事件),接收完后,再由这个线程唤醒当前线程。

至于更细点的就不好说了,毕竟键盘的输入都是驱动级的了,已经不能说是多线程了。

线程阻塞就是:暂停线程,由其它线程唤醒,自身无法唤醒
(自身唤醒的话应该叫休眠吧sleep,不过自身休眠了谁来接收数据)

 

 

2.

  127.0.0.1回环ip(loopback) / 本机ip

  netstat -a 查看端口使用情况

  

以后想到了再写 , 现在十周 周一 , 预计成品怎么也得是个多线程的 , 再搭一个图形界面。

11/6 15:23:58


 

更新22:59:20

晚上在hg机子上运行Server实际操作了一下发现了一些问题 , 总结一下就是对这个 buffer 以及reaLine方法还不太理解。

比如说你输完信息 , 按了回车 , 现在输入东西并按回车 不会显示在终端上 , 不过确实会发送到对方 , 即在对方的socket的 getOutputStream的 buffer里

比如你发完 hi了以后有输入了 , a+回车 *3

server接收到hi以后 回复 1 ,立即会收到 a ;再回复 1 , 立即回收到a , 直到把那三个a全接收完 。

 


 

昨天晚上说的好像不太对 , 情况应该是这样子的。

当某一方发完以后 , 因为等待对方而处于阻塞中 , 此时你再输入 “aa+回车” 则会进入system.in的buffer 里 (cmd里不会回显 , eclipse控制台会回显)

然后你需要等待收到对方消息后才能执行PrintWriter.println() , 而又因为此时你的 system inbuffer里已经有了“aa+回车” , 所以不需要再等待你输入(因为是readLine方法)就

可以立即执行PrintWriter.println(“aa”)。

 

其实问题说到底就是你发完后必须等着接收到了再发 , 即不能再等待接收的时候发送 , 等待接受的时候的输入会送到system.in的buffer里。

2017-11-07 21:19:49

posted @ 2017-11-06 15:25  codeplay_ch  阅读(394)  评论(0)    收藏  举报