第一节 | 第二节 | 第三节 | 第四节 | 第五节 | 第六节 | 第七节 | |||||
![]() |
|||||||||||
TCP是一种可靠的、基于连接的网络协议。网络上两进程采用Socket方式通信时,服务器构建ServerSocket对象,并侦听来自网络的客户连接请求。另一方为客户通过Socket主动向网络上的服务器发送连接请求,服务器接收客户连接请求,同时建立一个新的Socket对象,新的Socket对象负责与客户方继续交互。原服务器构建ServerSocket对象继续侦听来自网络的客户连接请求。图10-7描述基于连接的服务者、客户程序流程图。![]() 例10-4 利用Socket实现服务方和客户一对一的通信。 图10-7是服务方类TcpServer的类图。它描述了类TcpServer继承了Object类(可默认),以及它依赖的类,如:ServerSocket、Socket、DataInputStream、InputStream、IOException、OutputStream、PrintStream等,其中主要的是java.net包的Socket、ServerSocket类(见图10-8)。 ![]() 1)服务方源程序 package char10; import java.io.*; import java.net.*; public class TcpServer { static public void main(String args[]) throws IOException{ ServerSocket svrsoc=null; Socket soc=null; InputStream is=null; OutputStream os=null; //DataInputStream为InputStream 的子类。 DataInputStream in=null; //PrintStream为OutputStream的子类。 PrintStream out=null; try{ //构造ServerSockets对象,端口为8000, svrsoc=new ServerSocket(8000); /*让服务者永远等待,直到客户连接到该端口。服务者等待一个 *连接,返回新套接口soc,新套接口soc实现了与客户原建立的套接口 *的连接。 */ soc=svrsoc.accept(); //获得新套接口soc绑定的输入流InputStream对象 is=soc.getInputStream(); //构造数据输入流DataInputStream对象in in=new DataInputStream(is); //获得新套接口soc绑定的输出流OnputStream对象 os=soc.getOutputStream(); //构造输出流PrintStream 对象out out=new PrintStream(os); /*这里创建了数据输入流类对象in和输出流类对象out,服务者利用它们从客户接收输入信息(in)和向客户发送信息(out),同样,在客户端也应该建立这两个对象,用来与服务者进行双向通信。服务者向输出流发送的所有信息都成为客户的输入信息,而客户程序的输出的信息都送入服务者的输入流。 */ //获到客户方的IP地址,soc绑定了与它连接的客户地址 InetAddress clientIP=soc.getInetAddress(); //在服务方显示客户方的IP地址 System.out.println("Client's IP address:"+clientIP); int port; port=soc.getPort(); //得到客户方的端口 //在服务方显示客户方的端口 System.out.println("Client's port:"+port); //向客户发送… out.println("Welcome!..."); /*readLine()是数据输入流类中的一个方法,用于从输入流中读入对方发送的一行信息。*/ String str=in.readLine(); //在in上读一行 /*当输入流读入的不是”quit”时,将输入的数据写入输出流中,在屏幕上显示,然后继续从输入流中读入,不断循环,直到输入”quit”为止 */ while(!str.equals("quit")){ //如读出的不是“quit”,继续读 System.out.println("Client said:"+str); str=in.readLine(); } System.out.println("Client want to leave."); } catch(Exception e) { System.out.println("Error:"+e); } /*不断循环以上代码,直到客户输入”quit”或者str为null为止。最后在退出前, *关闭输入输出流及Socket */ finally{ is.close(); //关闭输入流 os.close(); //关闭输出流 soc.close(); //关闭socket System.exit(0); } } } (2)客户方源程序 1)服务方源程序 package char10; import java.io.*; import java.net.*; public class TcpServer { static public void main(String args[]) throws IOException{ ServerSocket svrsoc=null; Socket soc=null; InputStream is=null; OutputStream os=null; //DataInputStream为InputStream 的子类。 DataInputStream in=null; //PrintStream为OutputStream的子类。 PrintStream out=null; try{ //构造ServerSockets对象,端口为8000, svrsoc=new ServerSocket(8000); /*让服务者永远等待,直到客户连接到该端口。服务者等待一个 *连接,返回新套接口soc,新套接口soc实现了与客户原建立的套接口 *的连接。 */ soc=svrsoc.accept(); //获得新套接口soc绑定的输入流InputStream对象 is=soc.getInputStream(); //构造数据输入流DataInputStream对象in in=new DataInputStream(is); //获得新套接口soc绑定的输出流OnputStream对象 os=soc.getOutputStream(); //构造输出流PrintStream 对象out out=new PrintStream(os); /*这里创建了数据输入流类对象in和输出流类对象out,服务者利用它们从客户接收输入信息(in)和向客户发送信息(out),同样,在客户端也应该建立这两个对象,用来与服务者进行双向通信。服务者向输出流发送的所有信息都成为客户的输入信息,而客户程序的输出的信息都送入服务者的输入流。 */ //获到客户方的IP地址,soc绑定了与它连接的客户地址 InetAddress clientIP=soc.getInetAddress(); //在服务方显示客户方的IP地址 System.out.println("Client's IP address:"+clientIP); int port; port=soc.getPort(); //得到客户方的端口 //在服务方显示客户方的端口 System.out.println("Client's port:"+port); //向客户发送… out.println("Welcome!..."); /*readLine()是数据输入流类中的一个方法,用于从输入流中读入对方发送的一行信息。*/ String str=in.readLine(); //在in上读一行 /*当输入流读入的不是”quit”时,将输入的数据写入输出流中,在屏幕上显示,然后继续从输入流中读入,不断循环,直到输入”quit”为止 */ while(!str.equals("quit")){ //如读出的不是“quit”,继续读 System.out.println("Client said:"+str); str=in.readLine(); } System.out.println("Client want to leave."); } catch(Exception e) { System.out.println("Error:"+e); } /*不断循环以上代码,直到客户输入”quit”或者str为null为止。最后在退出前, *关闭输入输出流及Socket */ finally{ is.close(); //关闭输入流 os.close(); //关闭输出流 soc.close(); //关闭socket System.exit(0); } } } (2)客户方源程序 ![]() 图10-9描述TcpClient类图。它描述了类TcpClient继承了Object类(可默认),以及它依赖的类。 代码如下: package char10; import java.net.*; import java.io.*; public class TcpClient{ static public void main(String args[]) throws IOException{ Socket soc=null; InputStream is=null; OutputStream os=null; DataInputStream in=null; PrintStream out=null; String strin=null; try{ /* 客户先创建一个要与指定的服务者固定端口连接的Socket,假如上 *服务者程序在本机”localhost”上,则以下语句。 */ soc=new Socket("localhost",8000); System.out.println("Connecting to the Server..."); is=soc.getInputStream(); os=soc.getOutputStream(); in=new DataInputStream(is); out=new PrintStream(os); strin=in.readLine(); System.out.println("Server said:"+strin); byte bmsg[] = new byte[20]; System.in.read(bmsg); String msg=new String(bmsg,0); msg=msg.trim(); /*当从键盘读入的不是”quit”时,将键入的数据写入输出流中,然后继续从键盘读入,不断循环,直到输入”quit”为止 */ while(!msg.equals("quit")){ out.println(msg); System.in.read(bmsg); msg=new String(bmsg,0); msg=msg.trim(); } out.println(msg); } catch (Exception e) { System.out.println("Error: "+e); } finally{ is.close(); os.close(); soc.close(); System.exit(0); } } } 当运行服务器端程序时,开始没有任何显示,运行客户端程序后,将会显示下图结果的前两行,即显示客户端的IP地址和端口号,当客户端输入字符串后,服务器端的运行结果会显示相应的字符串,当客户端输入的字符串为“quit”时,服务器端显示“Client want to leave.”。 服务器端运行结果如图10-10所示: ![]() 客户端运行后,首先与服务器连接,然后显示服务器端发送过来的问候语“Welcome!”,接着,可以任意输入字符串,此时,服务器端会有相应的输出,直到输入“quit”,这时,客户端和服务器端程序都将结束。客户端运行结果如图10-11所示: ![]() 图10-12显示利用控制台视图的工具栏可以切换显示服务器一端或客户一端。 ![]() 图10-12 客户端运行结果 |
|||||||||||