本文是基于[1]之10.3.8节的阅读笔记,文末的两个java程序改自该节例10-2和10-3。
Client/Server结构的Java程序由两个独立的程序组成,每个程序的核心功能都由4个对象相互协作实现: 1 Socket,这是网络通信的核心; 2 信息发送者:是一个PrintWriter对象,与Socket的输出流绑定,负责发送信息,见Server程序第26行,Client程序第12行; 3 信息接收者:是一个BufferedReader对象,首先与Socket的输入流绑定,然后将输入的字节流转换为字符流,见Server程序第25行,Client程序第13行; 4 用户输入处理器:这个对象处理本地用户的输入,将输入字符串以合适的形式保存或者展现,不涉及网络,服务端程序代码见27行,客户端见11行; 之所以接收者需要加一层字节流到字符流的转换(用InputStreamReader实现),是因为网络传输的字节而非字符。
这类程序的基本结构由4个步骤组成: 1 创建Socket,Server端可分为两个子步骤(见程序第8-23行),第一步是创建一个ServerSocket对象,第二步是用它的accept方法在某一端口监听,等待客户端连接(程序运行到这里进入等待状态,也就是书中所谓的“阻塞”,在未收到客户端连接之前,不运行后面的代码);Client端比较简单(见程序第8行),创建一个Socket对象就OK了; 2 为Socket配置信息发送和接收者,服务端程序代码见25、26行,客户端见12、13行; 3 开始进行信息传递,代码见第29-36行(服务端)和15-22行(客户端),服务端运行到第30行is.readLine()等待socket的输入流,进入等待状态,与此同时客户端运行到第17行sin.readLine()等待用户输入,例如用户输入'aa'并回车,则程序执行到第20行is.readLine()(第20行)进入等待socket输入流状态,同时服务端收到了客户端os.flush()发送的信息并打印出来(第30行),得到用户输入(第32行)后向客户端发送(第35行),本次通信完成,客户端得到了socket的输出流后打印出来(第20行),本次通信完成。以上就此一次完整的do while循环内容。 4 通信结束,关闭Socket,见第37-46行(服务端)和24-31行(客户端)。
[1] 陈明:Java语言程序设计,清华大学出版社,2009.6
TalkServer.java(服务端程序) 01 import java.io.; 02 import java.net.; 03 04 public class TalkServer { 05 06 public static void main(String[] args) { 07 try{ 08 ServerSocket server = null; 09 try{ 10 server = new ServerSocket(4700); 11 System.out.println("Server Started."); 12 } 13 catch(Exception e){ 14 System.out.println("Can not listen to:"+e); 15 } 16 Socket socket = null; 17 try{ 18 socket = server.accept(); 19 System.out.println("Connected to Client."); 20 } 21 catch(Exception e){ 22 System.out.println("Error:"+e); 23 } 24 String line; 25 BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); 26 PrintWriter os = new PrintWriter(socket.getOutputStream()); 27 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); 28 System.out.println(); 29 do{ 30 System.out.println("Client "+is.readLine()); 31 System.out.println("To Client:"); 32 line = sin.readLine(); 33 System.out.println(); 34 os.println(line); 35 os.flush(); 36 } while(! line.equals("bye")); 37 os.close(); 38 is.close(); 39 socket.close(); 40 server.close(); 41 } 42 catch (Exception e){ 43 System.out.println("Error:"+e); 44 } 45 } 46 } TalkClient.java(客户端程序) 01 import java.io.; 02 import java.net.; 03 04 public class TalkClient { 05 06 public static void main(String[] args) { 07 try { 08 Socket socket = new Socket("127.0.0.1",4700); 09 System.out.println("Connected to Server."); 10 System.out.println(); 11 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); 12 PrintWriter os = new PrintWriter(socket.getOutputStream()); 13 BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); 14 String readline; 15 do{ 16 System.out.print("To Server:"); 17 readline = sin.readLine(); 18 os.println(readline); 19 os.flush(); 20 System.out.println("Server says:"+is.readLine()); 21 System.out.println(); 22 } 23 while (! readline.equals("bye")); 24 os.close(); 25 is.close(); 26 } 27 catch(Exception e){ 28 System.out.println("Error"+e); 29 } 30 } 31 }