java网络编程之简单客户端服务器_第1页
java网络编程之简单客户端服务器_第2页
java网络编程之简单客户端服务器_第3页
java网络编程之简单客户端服务器_第4页
java网络编程之简单客户端服务器_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、用Java开发网络软件非常方便和强大,Java的这种力量来源于他独有的一套强大的用于网络的 API,这些API是一系列的类和接口,均位于包和中。在这篇文章中我们将介绍套接字(Socket)慨念,同时以实例说明如何使用Network API操纵套接字,在完成本文后,你就可以编写网络低端通讯软件。什么是套接字(Socket)?Network API是典型的用于基于TCP/IP网络Java程序与其他程序通讯,Network API依靠Socket进行通讯。Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这

2、段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。如图1我们来分析一下图1,Host A上的程序A将一段信息写入Socket中,Socket的内容被Host A的网络管理软件访问,并将这段信息通过Host A的网络接口卡发送到Host B,Host B的网络接口卡接收到这段信息后,传送给Host B的网络管理软件,网络管理软件将这段信息保存在Host B的Socket中,然后程序B才能在Socket中阅读这段信息。假设在图1的网络中添加第三个主机Host C,那么Host A怎么知道信息被正确传送到Host B而不是被传送到Host C中了呢?基于TCP/IP网络中的每一个主机

3、均被赋予了一个唯一的IP地址,IP地址是一个32位的无符号整数,由于没有转变成二进制,因此通常以小数点分隔,如:,正如所见IP地址均由四个部分组成,每个部分的范围都是0-255,以表示8位地址。值得注意的是IP地址都是32位地址,这是IP协议版本4(简称Ipv4)规定的,目前由于IPv4地址已近耗尽,所以IPv6地址正逐渐代替Ipv4地址,Ipv6地址则是128位无符号整数。假设第二个程序被加入图1的网络的Host B中,那么由Host A传来的信息如何能被正确的传给程序B而不是传给新加入的程序呢?这是因为每一个基于TCP/IP网络通讯的程序都被赋予了唯一的端口和端口

4、号,端口是一个信息缓冲区,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数,范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于256的短口号保留给标准应用程序,比如pop3的端口号就是110,每一个套接字都组合进了IP地址、端口、端口号,这样形成的整体就可以区别每一个套接字t,下面我们就来谈谈两种套接字:流套接字和自寻址数据套接字。流套接字(Stream Socket)无论何时,在两个网络应用程序之间发送和接收信息时都需要建立一个可靠的连接,流套接字依靠TCP协议来保证信息正确到达目的地,实际上,IP包有可能在网络中丢失或者在传送过程中发生错误

5、,任何一种情况发生,作为接受方的 TCP将联系发送方TCP重新发送这个IP包。这就是所谓的在两个流套接字之间建立可靠的连接。流套接字在C/S程序中扮演一个必需的角色,客户机程序(需要访问某些服务的网络应用程序)创建一个扮演服务器程序的主机的IP地址和服务器程序(为客户端应用程序提供服务的网络应用程序)的端口号的流套接字对象。客户端流套接字的初始化代码将IP地址和端口号传递给客户端主机的网络管理软件,管理软件将IP地址和端口号通过NIC传递给服务器端主机;服务器端主机读到经过NIC传递来的数据,然后查看服务器程序是否处于监听状态,这种监听依然是通过套接字和端口来进行的;如果服务器程序处于监听状态

6、,那么服务器端网络管理软件就向客户机网络管理软件发出一个积极的响应信号,接收到响应信号后,客户端流套接字初始化代码就给客户程序建立一个端口号,并将这个端口号传递给服务器程序的套接字(服务器程序将使用这个端口号识别传来的信息是否是属于客户程序)同时完成流套接字的初始化。如果服务器程序没有处于监听状态,那么服务器端网络管理软件将给客户端传递一个消极信号,收到这个消极信号后,客户程序的流套接字初始化代码将抛出一个异常对象并且不建立通讯连接,也不创建流套接字对象。这种情形就像打电话一样,当有人的时候通讯建立,否则电话将被挂起。这部分的工作包括了相关联的三个类:InetAddress, Socket,

7、和 ServerSocket。 InetAddress对象描绘了32位或128位IP地址,Socket对象代表了客户程序流套接字,ServerSocket代表了服务程序流套接字,所有这三个类均位于包中。InetAddress类InetAddress类在网络API套接字编程中扮演了一个重要角色。参数传递给流套接字类和自寻址套接字类构造器或非构造器方法。InetAddress描述了32位或64位IP地址,要完成这个功能,InetAddress类主要依靠两个支持类Inet4Address 和 Inet6Address,这三个类是继承关系,InetAddrress是父类,Inet4Ad

8、dress 和 Inet6Address是子类。由于InetAddress类只有一个构造函数,而且不能传递参数,所以不能直接创建InetAddress对象,比如下面的做法就是错误的:InetAddress ia = new InetAddress ();但我们可以通过下面的5个工厂方法创建来创建一个InetAddress对象或InetAddress数组:. getAllByName(String host)方法返回一个InetAddress对象的引用,每个对象包含一个表示相应主机名的单独的IP地址,这个IP地址是通过host参数传递的,对于指定的主机如果没有IP地址存在那么这个方法将抛出一个U

9、nknownHostException 异常对象。. getByAddress(byte addr)方法返回一个InetAddress对象的引用,这个对象包含了一个Ipv4地址或Ipv6地址,Ipv4地址是一个4字节数组,Ipv6地址是一个16字节地址数组,如果返回的数组既不是4字节的也不是16字节的,那么方法将会抛出一个UnknownHostException异常对象。. getByAddress(String host, byte addr)方法返回一个InetAddress对象的引用,这个InetAddress对象包含了一个由host和4字节的addr数组指定的IP地址,或者是host和

10、16字节的addr数组指定的IP地址,如果这个数组既不是4字节的也不是16位字节的,那么该方法将抛出一个UnknownHostException异常对象。. getByName(String host)方法返回一个InetAddress对象,该对象包含了一个与host参数指定的主机相对应的IP地址,对于指定的主机如果没有IP地址存在,那么方法将抛出一个UnknownHostException异常对象。. getLocalHost()方法返回一个InetAddress对象,这个对象包含了本地机的IP地址,考虑到本地主机既是客户程序主机又是服务器程序主机,为避免混乱,我们将客户程序主机称为客户主机

11、,将服务器程序主机称为服务器主机。上面讲到的方法均提到返回一个或多个InetAddress对象的引用,实际上每一个方法都要返回一个或多个Inet4Address/Inet6Address对象的引用,调用者不需要知道引用的子类型,相反调用者可以使用返回的引用调用InetAddress对象的非静态方法,包括子类型的多态以确保重载方法被调用。InetAddress和它的子类型对象处理主机名到主机IPv4或IPv6地址的转换,要完成这个转换需要使用域名系统,下面的代码示范了如何通过调用getByName(String host)方法获得InetAddress子类对象的方法,这个对象包含了与host参数

12、相对应的IP地址:InetAddress ia = InetAddress.getByName ();一但获得了InetAddress子类对象的引用就可以调用InetAddress的各种方法来获得InetAddress子类对象中的IP地址信息,比如,可以通过调用getCanonicalHostName()从域名服务中获得标准的主机名;getHostAddress()获得IP地址,getHostName()获得主机名,isLoopbackAddress()判断IP地址是否是一个loopback地址。Socket类当客户程序需要与服务器程序通讯的时候,客户程序在客户机

13、创建一个socket对象,Socket类有几个构造函数。两个常用的构造函数是 Socket(InetAddress addr, int port) 和 Socket(String host, int port),两个构造函数都创建了一个基于Socket的连接服务器端流套接字的流套接字。对于第一个InetAddress子类对象通过addr参数获得服务器主机的IP地址,对于第二个函数host参数包被分配到InetAddress对象中,如果没有IP地址与host参数相一致,那么将抛出UnknownHostException异常对象。两个函数都通过参数port获得服务器的端口号。假设已经建立连接了,网

14、络API将在客户端基于Socket的流套接字中捆绑客户程序的IP地址和任意一个端口号,否则两个函数都会抛出一个IOException对象。如果创建了一个Socket对象,那么它可能通过调用Socket的 getInputStream()方法从服务程序获得输入流读传送来的信息,也可能通过调用Socket的 getOutputStream()方法获得输出流来发送消息。在读写活动完成之后,客户程序调用close()方法关闭流和流套接字,下面的代码创建了一个服务程序主机地址为,端口号为13的Socket对象,然后从这个新创建的Socket对象中读取输入流,然后再关闭流和Soc

15、ket对象。Socket s = new Socket (, 13);InputStream is = s.getInputStream ();/ Read from the stream.is.close ();s.close ();ServerSocket类由于SSClient使用了流套接字,所以服务程序也要使用流套接字。这就要创建一个ServerSocket对象,ServerSocket有几个构造函数,最简单的是ServerSocket(int port),当使用ServerSocket(int port)创建一个ServerSocket对象,port参数传递端

16、口号,这个端口就是服务器监听连接请求的端口,如果在这时出现错误将抛出IOException异常对象,否则将创建ServerSocket对象并开始准备接收连接请求。接下来服务程序进入无限循环之中,无限循环从调用ServerSocket的accept()方法开始,在调用开始后accept()方法将导致调用线程阻塞直到连接建立。在建立连接后accept()返回一个最近创建的Socket对象,该Socket对象绑定了客户程序的IP地址或端口号。由于存在单个服务程序与多个客户程序通讯的可能,所以服务程序响应客户程序不应该花很多时间,否则客户程序在得到服务前有可能花很多时间来等待通讯的建立,然而服务程序和

17、客户程序的会话有可能是很长的(这与电话类似),因此为加快对客户程序连接请求的响应,典型的方法是服务器主机运行一个后台线程,这个后台线程处理服务程序和客户程序的通讯。下面给出一个客户端和服务器的程序,客户端向服务器发送数据,服务器接收数据并用它生成一个结果,然后将结果返回给客户端,并在控制台上显示。服务器代码java 1. packageServer;2. 3. importjava.io.*;4. .*;5. importjava.util.*;6. importjava.awt.*;7. importjavax.swing.*;8. 9. publicclassS

18、erverextendsJFrame10. /Textareafordisplayingcontents11. privateJTextAreajta=newJTextArea();12. 13. publicstaticvoidmain(Stringargs)14. newServer();15. 16. 17. publicServer()18. /Placetextareaontheframe19. getContentPane().setLayout(newBorderLayout();20. getContentPane().add(newJScrollPane(jta),Borde

19、rLayout.CENTER);21. 22. setTitle(Server);23. setSize(500,300);24. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);25. setVisible(true);/Itisnecessarytoshowtheframehere!26. 27. try28. /Createaserversocket29. ServerSocketserverSocket=newServerSocket(8000);30. jta.append(Serverstartedat+newDate()+n);31.

20、 32. /Listenforaconnectionrequest33. Socketsocket=serverSocket.accept();34. 35. /Createdatainputandoutputstreams36. DataInputStreaminputFromClient=newDataInputStream(37. socket.getInputStream();38. DataOutputStreamoutputToClient=newDataOutputStream(39. socket.getOutputStream();40. 41. while(true)42.

21、 /Receiveradiusfromtheclient43. doubleradius=inputFromClient.readDouble();44. 45. /Computearea46. doublearea=radius*radius*Math.PI;47. 48. /Sendareabacktotheclient49. outputToClient.writeDouble(area);50. 51. jta.append(Radiusreceivedfromclient:+radius+n);52. jta.append(Areafound:+area+n);53. 54. 55.

22、 catch(IOExceptionex)56. System.err.println(ex);57. 58. 59. 客户端程序java1. packageClient;2. 3. importjava.io.*;4. .*;5. importjava.awt.*;6. importjava.awt.event.*;7. importjavax.swing.*;8. 9. publicclassClientextendsJFrameimplementsActionListener10. /Textfieldforreceivingradius11. private

23、JTextFieldjtf=newJTextField();12. 13. /Textareatodisplaycontents14. privateJTextAreajta=newJTextArea();15. 16. /IOstreams17. privateDataOutputStreamoutputToServer;18. privateDataInputStreaminputFromServer;19. 20. publicstaticvoidmain(Stringargs)21. newClient();22. 23. 24. publicClient()25. /Panelpto

24、holdthelabelandtextfield26. JPanelp=newJPanel();27. p.setLayout(newBorderLayout();28. p.add(newJLabel(Enterradius),BorderLayout.WEST);29. p.add(jtf,BorderLayout.CENTER);30. jtf.setHorizontalAlignment(JTextField.RIGHT);31. 32. getContentPane().setLayout(newBorderLayout();33. getContentPane().add(p,Bo

25、rderLayout.NORTH);34. getContentPane().add(newJScrollPane(jta),BorderLayout.CENTER);35. 36. jtf.addActionListener(this);/Registerlistener37. 38. setTitle(Client);39. setSize(500,300);40. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);41. setVisible(true);/Itisnecessarytoshowtheframehere!42. 43. try4

26、4. /Createasockettoconnecttotheserver45. Socketsocket=newSocket(localhost,8000);46. /Socketsocket=newSocket(6,8000);47. /Socketsocket=newSocket(drake.A,8000);48. 49. /Createaninputstreamtoreceivedatafromtheserver50. inputFromServer=newDataInputStream(51. socket.getInputStrea

27、m();52. 53. /Createanoutputstreamtosenddatatotheserver54. outputToServer=55. newDataOutputStream(socket.getOutputStream();56. 57. catch(IOExceptionex)58. jta.append(ex.toString()+n);59. 60. 61. 62. publicvoidactionPerformed(ActionEvente)63. StringactionCommand=e.getActionCommand();64. if(e.getSource

28、()instanceofJTextField)65. try66. /Gettheradiusfromthetextfield67. doubleradius=Double.parseDouble(jtf.getText().trim();68. 69. /Sendtheradiustotheserver70. outputToServer.writeDouble(radius);71. outputToServer.flush();72. 73. /Getareafromtheserver74. doublearea=inputFromServer.readDouble();75. 76.

29、/Displaytothetextarea77. jta.append(Radiusis+radius+n);78. jta.append(Areareceivedfromtheserveris79. +area+n);80. 81. catch(IOExceptionex)82. System.err.println(ex);83. 84. 85. 86. 运行结果如下如所在做一个服务器服务多个客户端时,可以简单的为买个客户端创建一个线程。相互独立的线程和指定的客户端进行通信,每个线程创建数据输入输出流向客户端发送接收数据。多线程服务器端的代码如下:java 1. packageMultiT

30、hreadServer;2. 3. importjava.io.*;4. .*;5. importjava.util.*;6. importjava.awt.*;7. importjavax.swing.*;8. 9. publicclassMultiThreadServerextendsJFrame10. /Textareafordisplayingcontents11. privateJTextAreajta=newJTextArea();12. 13. publicstaticvoidmain(Stringargs)14. newMultiThreadServ

31、er();15. 16. 17. publicMultiThreadServer()18. /Placetextareaontheframe19. getContentPane().setLayout(newBorderLayout();20. getContentPane().add(newJScrollPane(jta),BorderLayout.CENTER);21. 22. setTitle(MultiThreadServer);23. setSize(500,300);24. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);25. set

32、Visible(true);/Itisnecessarytoshowtheframehere!26. 27. try28. /Createaserversocket29. ServerSocketserverSocket=newServerSocket(8000);30. jta.append(MultiThreadServerstartedat+newDate()+n);31. 32. /Numberaclient33. intclientNo=1;34. 35. while(true)36. /Listenforanewconnectionrequest37. Socketsocket=s

33、erverSocket.accept();38. 39. /Displaytheclientnumber40. jta.append(Startingthreadforclient+clientNo+41. at+newDate()+n);42. 43. /Findtheclientshostname,andIPaddress44. InetAddressinetAddress=socket.getInetAddress();45. jta.append(Client+clientNo+shostnameis46. +inetAddress.getHostName()+n);47. jta.append(Client+clientNo+sIPAddressis48. +inetAddress.getHostAddress()+n);49. 50. /Createanewthreadfortheconnection51. Ha

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论