1 / 75

Advanced Network Programming

Advanced Network Programming. Ren Jiansi renjsv@cug.edu.cn. 2.4 套接口类( Socket 、 ServerSocket )概述

lilli
Download Presentation

Advanced Network Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Advanced Network Programming Ren Jiansi renjsv@cug.edu.cn

  2. 2.4套接口类(Socket、ServerSocket)概述 套接口是网络协议传输层提供的接口。套接口是进程之间通信的抽象连接点。它封装了端口、主机地址、传输层通信协议三方面内涵(见图3)。两个网络进程采用套接口方式通信时,两进程扮演的角色不同,它们使用的套接口也不同。主动请求服务的一方叫客户,它使用客户建立的套接口Socket,通过它主动与对方连接;服务者等待接收客户服务请求,提供服务,返回结果,它使用服务者套接口ServerSocket. 用户目前可以使用的两种套接口,即流套接口和数据报套接口。流套接口提供了双向的、有序的、无重复并且无记录边界的数据流服务。TCP即是一种流套接口协议;数据报套接口支持

  3. 双向的数据流,但并不保证是可靠、有序、无重复的,也就是说,一个以数据报套接口接收的信息的进程有可能发现信息重复了,或者和发出的顺序不同。数据报套接口的一个重要特点是它保留了记录边界。UDP是数据报套接口协议。双向的数据流,但并不保证是可靠、有序、无重复的,也就是说,一个以数据报套接口接收的信息的进程有可能发现信息重复了,或者和发出的顺序不同。数据报套接口的一个重要特点是它保留了记录边界。UDP是数据报套接口协议。 每一进程运行在该主机的一个对外开放的端口上。主机地址用其IP地址或域名地址表示(见图3)。一个端口与使用该端口的进程是对应的。端口常以整数编号,作为服务者可选择一个端口号,网络的客户以服务者主机和服务者选择的端口号与服务者连接。一些端口号是网络服务约定的,如80是WWW服务的缺省端口号。

  4. 图3 基于Socket的点对点通信

  5. A simple server (simplified code) // SimpleServer.java: a simple server program import java.net.*; import java.io.*; public class SimpleServer { public static void main(String args[]) throws IOException { // Register service on port 1234 ServerSocket s = new ServerSocket(1234); Socket s1=s.accept(); // Wait and accept a connection // Get a communication stream associated with the socket OutputStream s1out = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream (s1out); // Send a string! dos.writeUTF("Hi there"); // Close the connection dos.close(); s1out.close(); s1.close(); } }

  6. A simple client (simplified code) // SimpleClient.java: a simple client program import java.net.*; import java.io.*; public class SimpleClient { public static void main(String args[]) throws IOException { // Open your connection to a server, at port 1234 Socket s1 = new Socket("muu.oz.au",1234); // Get an input file handle from the socket and read the input InputStream s1In = s1.getInputStream(); DataInputStream dis = new DataInputStream(s1In); String st = new String (dis.readUTF()); System.out.println(st); // When done, just close the connection and exit dis.close(); s1In.close(); s1.close(); } }

  7. 1.套接口类(Socket) (1)构造方法 1)Socket(String host, int port) throws UnknownHostException,IOException 构造一个流套接口(即Socket对象),利用TCP协议将其连接至特定主机host的特定端口port上。 2)Socket(String host,int port,boolean stream) 构造一个套接口,而此套接口是流套接口(或TCP协议)还是数据报(datagram或UDP协议)套接口,则是由最后一个参数stream决定的。通信对方由主机名host和端口port来确定。

  8. 3)Socket(InetAddress address,int port) 构造一个流套接口,并把它连接到特定IP地址address的主机和特定端口port上。 4)Socket(InetAddress address,int port boolean stream) 构造一个套接口,此套接口是流套接口还是数据报(datagram)套接口,则是由最后一个参数stream决定的。通信对方由其主机IP地址address和端口port确定。 (2)套接口类提供的主要方法有: 1)InetAddress getInetAddress() 返回该套接口(Socket)所连接的IP地址。

  9. 2)int getPort() 返回该套接口(Socket)所连接的端口。 3)sychronized void close() throws IOException 关闭套接口 4)InputStream getInputStream() throws IOExcepiton 获得与套接口绑定的数据输入流对象。 5) InputStream getOutputStream() throws IOException 获得与套接口绑定的数据输出流对象。 2.服务者套接口类(ServerSocket)

  10. (1)构造方法 1)ServerSocket(int port) throws IOException 在指定的端口上构造一个服务者套接口,即构造一个ServerSocket实体对象。 2)ServerSocket(int port,int count) 构造一个服务者套接口,即构造一个ServerSocket实体对象,并且该对象是与指定的当地端口绑定。此外,可以对它进行监听。用户也可以通过将port设为0来将该对象与一个匿名端口相连接。 参数: count 容许等待对该ServerSocket对象的连接的个数。

  11. (2)服务者套接口类提供的主要方法: 1)Socket accept() throws IOException 服务者等待连接,该方法将阻塞当前服务线程,直到连接到来。该方法返回一个新的套接口类对象,通过该对象,与客户套接口进行通信。 2)void close() throws IOException 关闭套接口。 3使用TCP协议的Socket网络编程 1.基于客户/服务器方式的一对一的Socket 通信 TCP是一种可靠的、基于连接的网络协议。网络上的两进程采用Socket方式通信时,客户与服务器都必须建立各自的Socket,其中服务器构

  12. 图4 服务方、客户间的通信流程图

  13. 建ServerSocket对象,并侦听来自网络的客户连接请求,另一方作为客户,通过Socket向网络上的服务器发送连接请求。图4描述基于连接的服务者、客户程序流程图。建ServerSocket对象,并侦听来自网络的客户连接请求,另一方作为客户,通过Socket向网络上的服务器发送连接请求。图4描述基于连接的服务者、客户程序流程图。 图5是服务方类TcpServer不完全规范的UML模型简图。它描述了类TcpServer继承了Object类(可默认),以及它依赖的类,如:ServerSocket、Socket、DataInputStream、InputStream、IOException、OutputStream、PrintStream等,其中主要的是java.net包的Socket、ServerSocket类。

  14. 图5 服务方UML模型简图

  15. 例7 利用Socket实现服务方和客户一对一的通信。 (1)服务方源程序 package TcpServer; import java.io.*; import java.net.*; public class TcpServer { static public void main(String args[]) throws IOException{ ServerSocket svrsoc=null; Socket soc=null;

  16. InputStream is=null; OutputStream os=null; DataInputStream in=null; PrintStream out=null; try{ svrsoc=new ServerSocket(8000); soc=svrsoc.accept(); is=soc.getInputStream(); in=new DataInputStream(is); os=soc.getOutputStream(); out=new PrintStream(os); InetAddress clientIP=soc.getInetAddress();

  17. System.out.println("Client's IP address:"+ clientIP); int port; port=soc.getPort(); System.out.println("Client's port:"+port); out.println("Welcome!..."); String str=in.readLine(); while(!str.equals("quit")){ System.out.println("Client said:"+str); str=in.readLine(); } System.out.println("Client want to leave."); }

  18. catch(Exception e) { System.out.println("Error:"+e); } finally{ is.close(); os.close(); soc.close(); System.exit(0); } }} (2)客户方源程序

  19. 图1-6 客户方UML模型简图

  20. 图6描述了客户方不完全规范的UML模型简图。它描述了类TcpServer继承了Object类(可默认),以及它依赖的类。代码如下:图6描述了客户方不完全规范的UML模型简图。它描述了类TcpServer继承了Object类(可默认),以及它依赖的类。代码如下: 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;

  21. DataInputStream in=null; PrintStream out=null; String strin=null; try{ 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();

  22. System.out.println("Server said:"+strin); byte bmsg[] = new byte[20]; System.in.read(bmsg); String msg=new String(bmsg,0); msg=msg.trim(); while(!msg.equals("quit")){ out.println(msg); System.in.read(bmsg); msg=new String(bmsg,0); msg=msg.trim(); }

  23. out.println(msg); } catch (Exception e) { System.out.println("Error: "+e); } finally{ is.close(); os.close(); soc.close(); System.exit(0); } }}

  24. 服务器端运行结果如图7所示: 图7 服务器端运行结果

  25. 客户端运行结果如图8所示: 图8 客户端运行结果

  26. 2.综合示例:基于浏览器/服务器方式的网络聊天室 例8 如果聊天室有n个网友在聊天,每个网友聊天时其他网友都“看到“聊的内容。 ChatServer的运行结构如图1-9所示。该例涉及到线程、小应用程序、Socket等多方面知识。 图9 ChatServer的运行结构 (下页)

  27. (1)聊天服务者ChatServer实现源程序如下: import java.net.*; import java.io.*; import java.util.*; public class ChatServer { public static void main(String args[]) { ServerSocket socket=null; Vector m_threads=new Vector(); System.out.println("listen..."); try

  28. { socket=new ServerSocket(5555);} catch(Exception e) { System.out.println( "new ServerSocket()failed!"); return; } try { int nid=0; while(true) { Socket s=socket.accept();

  29. System.out.println("accepted"); ServerThread st=new ServerThread (s,m_threads); st.setID(nid++); m_threads.addElement(st); new Thread(st). start(); for(int i=0;i<m_threads.size();i++) { ServerThread st1= (ServerThread)m_threads.elementAt(i); st1.write("<#>welcome "+st.getID()+" to enter chatroom!");

  30. } System.out.println("Listen again..."); } } catch(Exception e) { System.out.println("Server is down...");} } } class ServerThread implements Runnable { Vector m_threads; Socket m_socket=null;

  31. DataInputStream m_in=null; DataOutputStream m_out=null; int m_nid; public ServerThread(Socket s,Vector threads) { m_socket=s; m_threads=threads; try { m_in=new DataInputStream (m_socket.getInputStream());

  32. m_out=new DataOutputStream (m_socket.getOutputStream()); } catch(Exception e) {} } public void run() { System.out.println("thread is running"); try { while(true)

  33. { String s=m_in.readUTF(); if (s==null) break; if (s.trim().equals ("leave")) for (int i=0;i<m_threads.size();i++) { ServerThread st=(ServerThread) m_threads.elementAt(i); st.write("*** "+getID()+" leave..."+"***"); } else for(int i=0;i<m_threads.size();i++) {

  34. ServerThread st=(ServerThread) m_threads.elementAt(i); st.write("<"+getID()+">"+s); } } } catch(Exception e) { e.printStackTrace(); } m_threads.removeElement(this); try { m_socket.close();}

  35. catch (Exception e){} } public void write (String msg) {synchronized(m_out) { try {m_out.writeUTF(msg);} catch(IOException e){} } } public int getID() {return m_nid;}

  36. public void setID(int nid) {m_nid=nid;} } (2)聊天者ChatApplet1源程序 /* <APPLET CODE=ChatApplet1.class WIDTH=200 HEIGHT=200> </APPLET>*/ import java.awt.*;

  37. import java.applet.*; import java.io.*; import java.net.*; public class ChatApplet1 extends Applet implements Runnable{ TextArea m_textarea; TextField m_textfield; DataInputStream m_in; DataOutputStream m_out; public void init() { setLayout(null);

  38. setSize(426,266); m_textarea=new TextArea(10,10); m_textfield=new TextField(); m_in=null; m_out=null; try{ URL url=getCodeBase(); InetAddress inetaddr= InetAddress.getByName(url.getHost()); Socket m_socket; System.out.println("Server:"+inetaddr+" "+url.getHost()+" "+url.getProtocol()); m_socket=new Socket(inetaddr,5555);

  39. m_in=new DataInputStream(m_socket.getInputStream()); m_out=new DataOutputStream(m_socket.getOutputStream()); } catch (Exception e) {System.out.println("Error:"+e);} setLayout(new BorderLayout()); add("Center",m_textarea); add("South",m_textfield); m_textarea.setEditable(false); new Thread(this).start();

  40. } public boolean handleEvent(Event event) { String b=m_textfield.getText(); if((event.target==m_textfield)&& (event.id==Event.ACTION_EVENT)) { m_textfield.setText(""); try{ m_out.writeUTF(b); } catch(IOException e){} return true;

  41. } else return super.handleEvent(event); } public void run() { try { while(true) { String s=m_in.readUTF(); if(s!=null) m_textarea.append(s+"\n"); } }

  42. catch(Exception e) { m_textarea.append("Network problem or Server down.\n"); m_textfield.setVisible(false); } } public void stop() { try {m_out.writeUTF("leave");} catch(IOException e){} } }

  43. UDP: no “connection” between client and server no handshaking UDP: transmitted data may be received out of order, or lost UDP provides unreliable transfer of groups of bytes (“datagrams”) between sockets application viewpoint Socket programming with UDP • UDP socket identified by: • dest IP address, dest port number • sender explicitly attaches IP address and port of destination to each packet • - server must extract IP address, port of sender from received packet

  44. Example: Java server (UDP) import java.io.*; import java.net.*; class UDPServer { public static void main(String args[]) throws Exception { DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; byte[] sendData = new byte[1024]; while(true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); Create datagram socket at port 9876 Create space for received datagram Receive datagram

  45. Example: Java server (UDP), cont String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivePacket.getAddress(); int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); sendData = capitalizedSentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); } } } Get IP addr port #, of sender Create datagram to send to client Write out datagram to socket End of while loop, loop back and wait for another datagram

  46. Example: Java client (UDP) import java.io.*; import java.net.*; class UDPClient { public static void main(String args[]) throws Exception { BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("hostname"); byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024]; String sentence = inFromUser.readLine(); sendData = sentence.getBytes(); Create input stream Create client socket Translate hostname to IP address using DNS

  47. Example: Java client (UDP), cont. Create datagram with data-to-send, length, IP addr, port DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); } } Send datagram to server Read datagram from server

  48. Client must contact server server process must first be running server must have created socket (door) that welcomes client’s contact Client contacts server by: creating client-local TCP socket specifying IP address, port number of server process When client creates socket: client TCP establishes connection to server TCP When contacted by client, server TCP creates new socket for server process to communicate with client allows server to talk with multiple clients source port numbers used to distinguish clients TCP provides reliable, in-order transfer of bytes between client and server application viewpoint Socket programming with TCP

  49. Example: Java client (TCP) import java.io.*; import java.net.*; class TCPClient { public static void main(String argv[]) throws Exception { String sentence; String modifiedSentence; BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); Socket clientSocket = new Socket("hostname", 6789); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); Create input stream Create client socket, connect to server Create output stream attached to socket

More Related