网络编程(接口socket)_第1页
网络编程(接口socket)_第2页
网络编程(接口socket)_第3页
网络编程(接口socket)_第4页
网络编程(接口socket)_第5页
免费预览已结束,剩余10页可下载查看

下载本文档

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

文档简介

1、使用Java语言还可以编写底层的网络通信程序,这是通过包中提供的Socket类以及ServerSocket等类实现的。本章讨论如何通过 socket使用TCP/IP或UDP协议实 现在网络上两个程序间建立连接并交换数据。Java套接字编程机器标识连接到Internet上的计算机使用IP地址或域名来唯一标识一台计算机,在局域网上的计算机则可以使用名称标识。要实现网络通信,首先需要知道计算机的地址。在包中提供了 InetAddress类对象来表示计算机地址。InetAddress类没有提供构造方法,要得到一个InetAddress类对象,需要使用该类的静态方法。 public static Ine

2、tAddress getByName(String host)返回给定主机名或点分十进制表示的主机的IP地址。 public static InetAddress口 getAllByName(String host)返回给定主机名或点分十进制表示的主机的所有IP地址数组。 public static InetAddress getLocalHost() 返回本地主机的 IP 地址。上述方法在指定的主机未知时将抛出UnknownHostException异常。InetAddress类其他方法: public String getHostName()返回该IP地址的主机名字符串。 public S

3、tring getHostAddress() 返回主机 IP 地址的字符串。 public byte口 getAddress() 返回四个元素的表示IP地址的字节数组。下面程序通过命令行给出一台主机的域名,程序将输出该机器的网络地址。程序 GetIPAddress.java import .*;public class GetIPAddresspublic static void main(String args) throws Exceptionif(args.length!=1)System.out.println("Usage:GetIPAddress DomainName&q

4、uot;);System.exit; InetAddress address = InetAddress.getByName(args0);System.out.println(address);System.out.println("Name:"+address.getHostName();System.out.println("Address:"+address.getHostAddress(); 要运行该程序,机器必须连到网络上。下面是程序运行的一个结果:包命等奘示苻Ge 11 PftdldrE4i s - JayaC:X>java |Get

5、iPAddi*e&G i-mjw = «cnuw. bhu B edu.c"21m7 . 176 . 3Naoe;ww/bhu.ediucn1Address:210.47 -176.3C:>.I 产图GetIPAddress程序的运行结果套接字通信在网络上,很多应用都是采用客户/服务器(C/S)结构的。实现网络通信必须将两台机器连接起来建立一个双向通信链路,这个双向通信链路的每一端称为一个套接字(socket)。1 .套接字的构成我们知道,在Internet上可以使用IP地址唯一标识一台主机。但一台主机可能提供多种 服务,而仅用IP地址还不能唯一

6、标识一个服务。因此通常使用一个整数来标识该机器上的某个服务,这个整数就是端口号(port)。端口号是用16位整数标识,共有65536个端口号。端口号并不是机器上实际存在的物理位置,而是一种软件上的抽象。端口号分为两类。一类是由因特网名字和号码指派公司ICANN分配给一些常用的应用层程序固定使用白熟知端口( well-known port),其数值为11024。例如HTTP服务的端口 号为80, FTP服务的端口号为 21。表1列出了几种常用的熟知端口号。表1常用服务的端口号服务FTPTelnetSMTPDNSHTTPSNMP端口号2123255380161另一类端口为一般端口,用来随时分配给请

7、求通信的客户进程。为了在通信时不致发生混乱,就必须把端口号和主机的IP地址结合在一起使用。一个TCP连接由它的两个端点来标识,而每一个端点又是由IP地址和端口号决定的。TCP连接的端点称为套接字(socket),套接字是由IP地址和端口号构成的,如图2所示:IP地址端口号图2套接字的构成这里,3为IP地址,1500为端口号,因此套接字为3, 1500。2 .套接字通信与套接字类一般来说,运行在一台特定机器上的某个服务器(如HTTP服务器)都有一个套接字绑定到该服务器上。服务器只是等待、监听客户的连接请求。在客户端,客户机需要知道运行服务器的主机名和端口号

8、。为了建立连接请求, 客户机试图与服务器机器上的指定端口号上的服务连接,这个请求过程如图3所示:seiver图3客户向服务器请求连接client如果正常,服务器将接受连接请求。一旦接受了请求,服务器将创建一个新的绑定到另 一个端口号的套接字, 然后使用该套接字与客户通信。 这样,服务器可以使用原来的套接字 继续监听连接请求,如图 4所示。图4服务器接受客户的连接在客户端,如果连接被接受,就会创建一个套接字(socket),客户就可以使用该套接字与服务器通信。注意,客户端的套接字并没有绑定到与服务器连接的端口号上,相反客户被指定客户程序所在机器上的一个端口号上。现在客户与服务器就可以读写套接字进

9、行通信 了。为了实现套接字通信,在 包中提供了两个类:Socket和ServerSocket。它们分别实现连接的客户端和服务器端的套接字。Socket类的常用构造方法: public Socket (String host, int port) throws UnknownHostException , lOException 创建 一个流式套接字对象并将其连接到命名主机的指定端口上。host为主机名,port为端口号。 public Socket (InetAddress address, int port) throws IOException 创建一个流式套接 字对象并将其连接到指定IP

10、地址的指定端口上。address为主机的IP地址,port为端口号。 public Socket (String host, int port, InetAddress localAddr, int localPort) throws IOException public Socket (InetAddress address, int port, InetAddress localAddr, int localPort) throws IOExceptionSocket类提供的主要方法有: public InetAddress getInetAddress() 返回该套接字所连接的IP 地址

11、。 public int getPort()返回该套接字所连接的远程端口号。 public synchronized void close() throws IOException 关闭套接字对象。 public InputStrean getInputStream() throws IOException 获得套接字绑定的数据输入 public OutputStream getOutputStream() throws IOException 获得套接字绑定的数据 输出流。ServerSocket类用在服务器端。客户与服务器通信,客户向服务器提出请求,服务器监 听请求,一旦监听到客户请求,服

12、务器也要建立一个套接字。这可通过ServerSocket类实现。ServerSocket类的构造方法如下: ServerSocket(int port)创建绑定到指定端口port上的服务器套接字。 ServerSocket(int port ,int backlog) 参数backlog指定最大的队列数,即服务器所能支持的最大连接数。 ServerSocket(int port ,int backlog, InetAddress bindAddr)参数 bindAddr 为所绑定的 地址。上面的构造方法都声明了抛出©Exception异常,因此创建对象时应该捕获异常或声明抛出异常。注

13、意,因为有些端口号已被特殊的服务占用,所以应该选择大于1024的端口号。ServerSocket类提供的主要方法: public Socket accept。throws IOException 该方法是 ServerSocket 类的重要方法,调 用该方法将阻塞当前系统服务线程,直到有客户连接。当有客户连接时,该方法返 回一个Socket对象。正是通过该 Socket对象,服务器才可以与客户通信。 public void close() throws IOException 关闭 ServerSocket对象。3. 一个简单的客户和服务器通信的实例无论一个套接字的通信功能多么齐全、程序多么复

14、杂,其基本结构都是一样的,都包括以下四个基本步骤:(1)创建socket对象;(2)打开连接到socket的输入输出流;(3)按照一定协议对 socket进行读写操作;(4)关闭 socketo图5说明了服务器和客户端所发生的动作。服务器端ServerSocket(port #) ss.accept() 得到socket对象OutputStreamInputStream close()客户端Socket(host,port #)得到socket对象OutputStreamInputStreamclose()图5通信双方建立连接的过程在服务器端,首先指定一个端口号,创建一个ServerSocke

15、t对象。然后调用 accept()方法等待客户连接。如果客户请求一个连接,服务器使用accept()方法将返回一个Socket对象。在客户端,用指定的服务器主机名或IP地址及端口号创建一个 Socket对象,该对象试图连接到指定主机指定端口的服务。当两端都返回Socket对象后,就可以分别在 Socket对象上调用 getInputStream()和getOutputStream()方法,得到输入输出流对象。这里要注意,服务器端的输出流对应于客户 端的输入流,服务器端的输入流对应于客户端的输出流。双方建立了输入输出流后就可以进行通信了。最后,通信结束应该调用close()方法关闭套接字,释放连

16、接的资源。下面是一个简单的字符界面的聊天程序。在服务器端使用端口号4700创建服务器套接字。服务器端程序如下:程序 ServerDemo.javaimport java.io.*;import .*;public class ServerDemopublic static void main(String args口儿tryServerSocket server = new ServerSocket(4700);Socket socket = server.accept();String line;BufferedReader is = new BufferedReader(new Input

17、StreamReader( socket.getInputStream();PrintWriter os = new PrintWriter( socket.getOutputStream();BufferedReader sin = new BufferedReader(new InputStreamReader( System.in);System.out.println("Client:"+ is.readLine();System.out.print("Server:");line=sin.readLine();while(!line.equal

18、s("bye")os.println(line);os.flush();System.out.println("Client:"+is.readLine();System.out.print("Server:");line=sin.readLine();sin.close();os.close();is.close();socket.close();server.close();catch(Exception e)System.out.println("Error:"+e);客户端端程序如下:程序 ClientDe

19、mo.javaimport java.io.*;import .*;public class ClientDemopublic static void main(String args口儿trySocket socket=new Socket(" server",4700);BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();PrintWriter os=new PrintWriter(socket.getOutputStream();BufferedReade

20、r sin=new BufferedReader(new InputStreamReader(System.in);String readline;System.out.print("Client:");readline=sin.readLine();while(!readline.equals("bye")os.println(readline);os.flush();System.out.println("Server:"+is.readLine();System.out.print("Client:");re

21、adline=sin.readLine();sin.close();os.close();is.close();socket.close();catch(Exception e)System.out.println("Error:"+e);该程序首先建立一个 Socket对象,其中“server”为服务器机器名,4700为服务器提供 连接服务的端口号。如果在一个机器上测试该程序,可以将“ server”改为所在机器的名称 或使用“localhost”,也可以使用“ ”地址。要测试该程序,应该首先运行服务器程序,然后运行客户程序,并且客户程序先向服务器发送消

22、息。图6和7分别给出了该程序的运行效果。图6服务器端程序运行效果Clientare 叩u?SeFwei*'Fine.yen!Client-I 口I 乂 I图7客户端程序运行效果4.为多个客户提供服务在上面的例子中,服务器只能为一个客户提供服务。在实际应用中,往往是在服务器机器上运行一个服务器,它接收来自其他多个客户的请求,为多个客户提供服务。下面程序提供的功能是客户程序向服务器发送一个表示圆的半径的数,服务器为其计算圆的面积并将计算结果发送给客户。这里为实现服务器为多个客户服务,使用了多线程的机制。下面是服务器端程序:程序 MultiThreadServer.javaimport ja

23、va.io.*;import .*;public static voidmain(String口args)tryServerSocket serverSocket = new ServerSocket(8000);int clientNo=1;while(true)Socket connectToClient = serverSocket.accept();System.out.println("Start thread for client "+clientNo);InetAddress clientInetAddress = connectToClient.getIne

24、tAddress();System.out.println("Client "+clientNo+" 's host name is " +clientInetAddress.getHostName();System.out.println("Client "+clientNo+" 's IP address is " +clientInetAddress.getHostAddress();HandleClient thread = new HandleClient(connectToClient)

25、; thread.start();clientNo+;catch(IOException ex) System.err.println(ex);class HandleClient extends Threadprivate Socket connectToClient;public HandleClient(Socket socket) connectToClient = socket;public void run()tryDataInputStream isFromClient = new DataInputStream( connectToClient. getInputStream(

26、);DataOutputStream osToClient = new DataOutputStream( connectToClient. getOutputStream();while(true)double radius = isFromClient.readDouble();System.out.println("radius received from client:"+radius); double area = radius*radius*Math.PI;osToClient.writeDouble(area);osToClient.flush();Syste

27、m.out.println("Area is:"+area);catch(IOException ex)System.err.println(ex);下面是客户端程序:程序 Client.javaimport java.io.*;import .*;import java.util.*;public class Clientpublic static voidmain(String口args)trySocket connectToServer = new Socket("localhost",8000);DataInputStream isFromSer

28、ver = new DataInputStream( connectToServer.getInputStream();DataOutputStream osToServer = new DataOutputStream( connectToServer.getOutputStream();while(true)System.out.print("Please input a radius:");Scanner sc = new Scanner(System.in);double radius = sc.nextDouble();osToServer.writeDouble

29、(radius);osToServer.flush();double area = isFromServer.readDouble();System.out.println("Area received from server:"+area); catch(IOException ex)System.err.println(ex);该程序的运行结果如图 6和7所示:图6服务器端程序运行效果图7客户端程序运行效果数据包通信上一节讲的socket通信是一种流式通信,本节讨论通过socket实现数据包通信。1流式通信和数据包通信当编写网络程序时,有两种通信可供选择:流式通信和数据

30、包通信。流式通信使用TCP(Transfer Control Protocol)协议,该协议是面向连接的协议。使用这 种协议要求发送方和接收方都要建立socket连接,一旦两个 socket建立起来,它们就可以进行双向通信,双方都可以发送和接收数据。数据包通信使用用户数据包协议UDP(User Datagram Protocol),该协议是一种无连接的协议。使用这种协议通信,每个数据包都是一个独立的信息单元,它包括完整的目的地址, 数据包在网络上以任何可能的路径传往目的地,因此数据能否到达目的地、到达的时间以及内容的正确性都是不能保证的,该协议提供的是不可靠的服务。在网络的传输层既然提供了两种

31、协议,那么在实际的应用中到底应该使用哪种协议?这要取决于不同的应用情况,下面是两种协议的比较:使用UDP时,每个数据包都给出了完整的地址信息,因此无需建立发送方和接收方的连接。对于TCP,由于它是一个面向连接的协议,在通信之前必须建立双方的连接,因此在TCP中多了一个建立连接的时间。使用UDP传输数据时是有大小限制的,每个数据包必须不大于64KB。而使用TCP就没有这方面的限制,一旦连接建立起来,就可以传输大量的数据。UDP是不可靠的协议,发送方发送的数据不一定以相同的次序到达接收方。而TCP是可靠的协议,它确保接收方完全正确地获取发送方所发送的数据。TCP使用较广泛,如TELNET远程登录、

32、FTP文件传输都需要不定长度的数据可靠 地传输,因此需要使用 TCP协议。相比之下 UDP比较简单,而且仅需要较少的监护,因此 常用于局域网分散系统中的 client/server应用程序。2 DatagramSocket 和 DatagramPacket 包提供了 DatagramSocket 类和 DatagramPacket 类,DatagramSocket 用于在程序 之间建立传送数据包的通信连接, DatagramPacket则用来表示一个数据包。 利用这两个类程 序员可以很方便地编写使用 UDP协议的socket客户和服务器通信程序。1. DatagramSocket 类Datag

33、ramSocket类的构造方法有: public DatagramSocket(int port) throws SocketException创建一个数据包套接字,并将它绑定在本地主机指定的的端口上。 public DatagramSocket。throws SocketException 创建一个数据包套接字,并将它绑 定在本地主机一个可用的端口上。DatagramSocket类的常用方法有: public void receive(DatagramPacket p) throws IOException该方法用来接收一个报文, 参数p用来保存接收的报文。 该方法会阻塞接收者, 直到有 一

34、个报文到达套接字。 为了防止对方由于某种原因可能使接收者永远阻塞,一般接收者设置一个计时器,如果收不到对方报文,计时器结束,接收者会作出处理。 public void send(DatagramPacket p) throws IOException该方法用来发送一个报文,参数 p保存了要发送的报文。报文包括数据、接收者的IP地址及其端口。2. DatagramPacket 类DatagramPacket类的构造方法有:ppublic DatagramPacket(byte口 buf, int length)参数buf为数据包文缓冲区,length为缓冲区的长度。该构造方法创建的对象用于接收

35、数据包。在接受数据之前,应该使用该构造方法创建一个DatagramPacket对象,给出接收数据的缓冲区及长度。然后调用DatagramSocket的receive。方法等待数据包的到来,receive。方法将一直等待,直到有一个数据包到来。例如:DatagramPacket packet = new DatagramPacket(buf,1024);socket.receive(packet); public DatagramPacket(byte buf, int length, InetAddress address, int port)参数buf为数据包文缓冲区,length为缓冲区的

36、长度,address为接收方的地址,port为 接收方数据包套接字绑定的端口号。该构造方法创建的对象用于发送数据包。在发送数据前,也要生成一个新的一个 DatagramPacket对象,在给出发送方的数据缓 冲区及长度的同时,还要给出完整的目标地址,包括 IP地址和端口号。发送数据是通过 DatagramSocket的send()方法实现的,send()方法根据目的地址选择路径,以传送数据包。 例如:DatagramPacket packet = new DatagramPacket(msg, send.length(), clientIP, clientPort);socket.send(p

37、acket);DatagramPacket类的常用方法有: public InetAddress getAddress()获得报文发送者的IP 地址。 public int getPort()获得报文发送者的端口。 public int getLength()返回发送或接收的数据长度。 public byte getData() 返回数据缓冲区。3 一个简单的数据包通信的例子用数据包编写客户/服务器程序时,无论是客户方还是服务器方,首先都要建立一个 DatagramSocket对象,用来接收或发送数据包,然后使用DatagramPacket类对象作为传输数据的载体。下面的实例通过 UDP实现通

38、信。该实例实现的功能是客户端向服务器端发送一个字符 串,服务器端接收该字符串,然后将其转换成大写字母,再发送到客户端。1 .服务器方的实现程序 UDPServer.javaimport .*;import java.io.*;public class UDPServerpublic static void main(String args口儿byte buf = new byte1024;tryDatagramSocket socket = new DatagramSocket(8888);System.out.println("Server is waiting.");w

39、hile(true)用于接收数据的数据包DatagramPacket packet = new DatagramPacket(buf,1024);socket.receive(packet);String data = new String(buf,0,packet.getLength();if(data.equals("bye")break;System.out.println("Client said:"+data);String send = data.toUpperCase();InetAddress clientIP = packet.getA

40、ddress();int clientPort = packet.getPort();byte口 msg = send.getBytes();用于发送数据的数据包DatagramPacket sendPacket = new DatagramPacket( msg,send.length(),clientIP,clientPort);socket.send(sendPacket);socket.close();System.out.println("Server is closed.");catch(Exception e)e.printStackTrace();2 .客户

41、方的实现程序 UDPClient.javaimport .*;import java.io.*;public class UDPClientpublic static void main(String args口儿byte bufsend = null;String sendMessage = null;tryDatagramSocket socket = new DatagramSocket();BufferedReader sysin = new BufferedReader( new InputStreamReader(System.in);while(true)System.out.p

42、rintln("Waiting for input a line text."); sendMessage = sysin.readLine();bufsend = sendMessage.getBytes();用于发送数据的数据包DatagramPacket packet = new DatagramPacket( bufsend,sendMessage.length(), InetAddress.getLocalHost(),8888);socket.send(packet);if(sendMessage.equals("bye") break;by

43、te bufrec=new byte1024;用于接收数据的数据包DatagramPacket receivePacket = new DatagramPacket(bufrec,1024);socket.receive(receivePacket);String received = new String(receivePacket.getData();System.out.println("From Server:"+received);socket.close();catch(Exception e) e.printStackTrace();该程序的运行结果如图 8和

44、9所示:-joljdL :Fi. 1 a-sMiikoi- S e £tw u"a JCr nt or ¥3 liScrwcr is wait.Client said:what you see is uhat you get«图8服务器端程序运行效果二:¥ i. lasMinox- S e £ tv ua A JCi- ih nt or IT3 li-glxlWait ingi for input a line text.what von see is what you get. Fn Server=WMftT YOU SEE IS

45、UHftT VOU GET,图9客户端程序运行效果作业:3 .简述什么是套接字?它由哪些部分组成?它有什么作用?4 .套接口是为下面哪一项编码?()A.端口号B. IP地址C.端口号和IP地址D.都不是5 .为了等待客户的一个连接请求,服务器应该使用下面哪个类?()A. SocketB. SocketServerC. ServerD. URL6 .当使用带一个主机地址参数的构造方法创建一个新的Socket实例时:(A. Java试图在Internet上建立一个与该主机的连接。B. Java启动一个运行在该主机上的一个服务器。C.直到调用了 Socket的accept。方法,否则什么也不会发生。

46、A. sock.accept();C. sock.getOutputStream();7. 对一个给定的 Socket对象sock,为了获得一个输出流,下面哪个语句是正确的? )B. sock.getDataOutputStream();D. new DataOutputStream(sock);8. ServerSocket的accept。方法返回的类型是()。A. SocketB.ServerSocketC. ServerD.URL9. TCP 主要用于() 。A. 在 Internet 上标识基于点分十进制的地址或域名。B. 保证数据包按照发送的顺序到达。C. A 和 B 都正确D. A 和 B 都不正确12.利用Java的JFrame类实现一个图形用户界面的程序,它的功能是接受用户输入的 一个主机名,利用InetAddress 类查找出它的IP 地址并显示出来。14. 利用 Socket 类和 ServerSocket 类编写一对客户机/服务器程序,建立套接字通信管道,并将一个文件从一台机器传到另一台机器。17分析以下网络通信多线程程序功能。/SocketServer.javaimport .*;import java.io.*;public class

温馨提示

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

评论

0/150

提交评论