410 likes | 548 Views
JAVA NETWORKING. OUTLINE. Networking What is Socket InetAddress 類別 URL 類別 TCP socket Socket I/O UDP socket. (Peer to Peer) Protocol. interfaces. InterNet. physical layer. physical layer. NETWORK. TCP/IP network protocal. host. server. process. process. socket. socket.
E N D
OUTLINE • Networking • What is Socket • InetAddress類別 • URL類別 • TCPsocket • Socket I/O • UDP socket
(Peer to Peer) Protocol interfaces InterNet physical layer physical layer NETWORK • TCP/IP network protocal
host server process process socket socket TCP with buffers, variables TCP with buffers, variables SOCKET • process sends/receives messages to/from its socket • socket analogous to door • sending process shoves message out door • sending process relies on transport infrastructure on other side of door which brings message to socket at receiving process controlled by app developer Internet controlled by OS
SOCKET • Berkeley UNIX提出Socket的概念,將網路連線簡化為資料流(data stream)的概念,這個資料流在客戶端與伺服端各有一個接口(port),而資料流就像是在一個連接兩接口的纜線中傳遞,程式設計人員使用 Socket的概念來撰寫網路連線程式,只要處理主機資訊與連接埠,而不用關心底層的瑣碎運作。 • Socket將網路連線也視作一種輸出入的動作,資料的傳遞就像是將資料寫入與讀入。
JAVA.NET • java.net這個package底下,也提供了類似socket的類別,讓我們不必處理底層網路的東西。 • Java.net.InetAddress • Java.net.socket • Java.net.ServerSocket • Java.net.DatagramSocket
IP (Internet Protocol) address that can exist in two forms: • DNS form: www.cs.nccu.edu.tw • IP form: 140.119.162.53
INETADDRESS類別 • 可用來包裝與進行網址處理的相關操作 • InetAddress主要包括兩個欄位,即名稱與位址,名稱即像是www.cs.nccu.edu.tw這樣的名稱, 而位址則是IP位址,我們可以使用getHostName()與getHostAddress()方法分別取得這兩個資訊。
INETADDRESS類別 • 以下幾種靜態方法傳回InetAddress物件: public static InetAddressInetAddress.getLocalHost() public static InetAddress InetAddress.getByName(String hostname) public static InetAddress[] InetAddress.getAllByName(String hostname)
INETADDRESS類別 執行結果:www.cs.nccu.edu.tw/140.119.162.53 String host = "www.cs.nccu.edu.tw"; try { InetAddress address = InetAddress.getByName(host); System.out.println(address); } catch (UnknownHostException e) { System.out.println("Could't find"+host); }
URL類別 • URL 類別可以提供URL(Uniform Resource Locator)的Protocol、Host、Port、File、named anchor與URLStreamHandler等資訊 • URL的建構有以下方法: • public URL(String url) • public URL(String protocol, String host, String file) • public URL(String protocol, String host, int port, String file) • public URL(URL u,String s)
URL類別 • URL類別可以由以下幾個方法取得資訊: • public String getProtocol() • public String getHost() • public int getPort() • public String getFile() • public String getRef() • URL類別有三個方法可以取得指定的URL資料: • public final InputStream openStream() • public URLConnection openConnection() • public final Object getContent()
TCP&UDP • TCP (Transmission Control Protocol) is a connection-based protocol that provides a reliable flow of data between two computers. =>java.net.Socket • UDP (User Datagram Protocol) is a protocol that sends independent packets of data, called datagrams, from one computer to another with no guarantees about arrival. UDP is not connection-based like TCP. =>java.net.DatagramSocket
TCP SOCKET • Interface • SocketImplFactory • SocketOptions • Class • java.net.ServerSocket • java.net.Socket • java.net.SocketImpl • Exception • java.net.BindException • java.net.ConnectException • java.net.NoRouteToHostException • java.net.ProtocolException • java.net.SocketException ServerSocket accept Socket read write write read close close Server Client
JAVA.NET.SOCKET • Socket的建構有以下方法: • public Socket(String host, int port) • public Socket(InetAddress host, int port) • public Socket(String host, int port, InetAddress interface, int localPort) • public Socket(InetAddress host, int port, InetAddress interface, int localPort)
JAVA.NET.SOCKET • 在建立了Socket物件之後,可以取得Socket物件的相關資訊,例如:取得Socket連接對象位址public InetAddress getInetAddress() 取得連接對象連接埠public int getPort() 取得本機連接埠public int getLocalPort() 取得本機位址public inetAddress getLocalAddress()
JAVA.NET.SERVERSOCKET • 實作一個伺服器,可以使用ServerSocket類別,它包括了伺服器傾聽與客戶端連線的方法 • ServerSocket的建構有以下方法: • public ServerSocket(int port) • public ServerSocket(int port, int queuelength) • public ServerSocket(int port, int queuelength, InetAddress bindAddress) • port是所指定要繫結的連接埠,queuelength用來指定外來連線的佇列長度,bindAddress指定要繫結至哪一個網路介面
JAVA.NET.SERVERSOCKET • 當要傾聽連線或關閉連線時,可以使用accept()與close()方法: public Socket accept() public void close() • accept()傳回的是有關連線客戶端的Socket物件資訊,可以用它來取得客戶端的連線資訊,或關閉客戶端的連線。
import java.io.IOException; import java.net.*; public class SimpleServer { public static void main(String[] args) { int listenPort = 8888; ServerSocket serverSocket = null; Socket clientSocket = null; try { serverSocket = new ServerSocket(listenPort); // build a ServerSocket for listening the connection on port 8888 System.out.println("the serversocket information:" + serverSocket.getLocalSocketAddress()); System.out.println("wait to client...."); clientSocket = serverSocket.accept(); System.out.println("the client information:" + clientSocket.getRemoteSocketAddress()); } catch (IOException e) { System.out.println("some error:" + e.getMessage()); } } } accept得到已建立連線的socket。
import java.io.*; import java.net.Socket; import java.net.UnknownHostException; public class SimpleClient { public static void main(String[] args) { String serverIP = "127.0.0.1"; int serverPort = 8888; try { Socket socket = new Socket(serverIP, serverPort); System.out.println("client information:"+socket.getLocalSocketAddress()); System.out.println("Server information:"+socket.getRemoteSocketAddress()); socket.close(); } catch (UnknownHostException e) { System.out.println("Error:"+e.getMessage()); } catch (IOException e) { System.out.println("Error:"+e.getMessage()); } } } 與Server連線的 Socket
SOCKET I/O • 如果要取過Socket物件接受或輸出資訊,可以使用getInputStream()與getOutputStream()兩個方法,就如同檔案I/O 一樣,只要將它當作串流資料來處理即可。 • public InputStream getInputStream() throws IOException • public OutputStream getOutputStream() throws IOException • 可以再用bufferedReader, bufferedWriter包裝
GETINPUTSTREAM() • getInputStream用以取得所連結的輸入資料流(Input Stream),並以java.io.InputStream形式表示,通常會以DataInputStream或BufferedReader類別承接InputStream資料流。 • java.io.DataInputStream • java.io.BufferedReader • DataInputStream din = • new DataInputStream(socket.getInputStream()); • BufferedReader bufin = new BufferedReader( • new InputStreamReader(socket.getInputStream()));
GETINPUTSTREAM() 當輸入資料流建立之後,便可使用輸入資料流的read方法,讀取對方傳送來的資訊。 DataInputStream: • read • readByte • readChar • readDouble • readFloat • readFully • readInt • readUTF • …… • BufferedReader: • read • readLine • String inData = din.readUTF(); • String str = bufin.readLine();
GETOUTPUTSTREAM() • 欲傳送資料至對方,需先以getOutputStream取得輸出資料流(Output Stream),此方法會以java.io.OutputStream形式表示,通常會以DataOutputStream、BufferedWriter或PrintStream類別轉承OutputStream資料流: • java.io.DataOutputStream • java.io.BufferedWriter • java.io.PrintStream • PrintStream out = • new PrintStream(socket.getOutputStream()); • DataOutputStream dout = • new DataOutputStream(clientSocket.getOutputStream());
GETOUTPUTSTREAM() 當輸出資料流建立之後,便可使用輸出資料流的write方法,傳送資料至Client端。 DataOutputStream: • write • writeBoolean • writeByte • writeBytes • writeChar • writeChars • writeInt • writeUTF • …… • Bufferedwriter: • write • PrintStream: • println(String) • out.println(“Hello World”); • dout.writeUTF(“Hello World”);
使用OUTPUTSTREAM • 送完一個字串後,請加flush()這個方法,避免還留在buffer裡頭。 • out.flush(); • 當不用時,請加close()關閉來釋放資源。 • out.close();
SOCKET I/O • Example:client傳送字串給serverserver會回傳字串給client。
import java.io.*; import java.net.*; public class EchoTCPServer { public static void main(String[] args) { int listenPort = 8888; ServerSocket serverSocket = null; Socket clientSocket = null; try { serverSocket = new ServerSocket(listenPort); System.out.println("wait to client...."); clientSocket = serverSocket.accept(); PrintStream out = new PrintStream(clientSocket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String str = in.readLine(); System.out.println("the client comes message :" + str); out.println(str);//送回同樣的字串給client out.flush(); out.close(); in.close(); clientSocket.close(); } catch (IOException e) { System.out.println("some error:" + e.getMessage()); } } }
import java.io.*; import java.net.Socket; import java.net.UnknownHostException; public class SimpleClient { public static void main(String[] args) { String serverIP = "127.0.0.1";//或是 "localhost" int serverPort = 8888; try { Socket socket = new Socket(serverIP, serverPort); PrintStream out = new PrintStream(socket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("please key the message to server:"); BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in)); out.println(fromUser.readLine()); out.flush();
String str = in.readLine(); System.out.println("the server comes message : " + str); out.close(); in.close(); socket.close(); } catch (UnknownHostException e) { System.out.println("Error:"+e.getMessage()); } catch (IOException e) { System.out.println("Error:"+e.getMessage()); } } }
CONCURRENT SERVER SOCKET • 前面的EchoTCPServer只能處理一個client,所以當有很多client同時向Server連線時,就無法處理了。為了要處理多人連線,我們的Server端程式就要用執行緒(Thread)為每一個Client端建立各自的執行緒,來處理每個要求。
public class ConcurrentServer { • public static void main(String[] args) • throws IOException { • int listenPort = 8888; • ServerSocket serverSocket = null; • Socket clientSocket = null; • try { • serverSocket = new ServerSocket(listenPort);// build a ServerSocket • // for listening the • // connection on port • // 8888 • System.out.println("the server information:" • + serverSocket.getLocalSocketAddress()); • Thread thread = null; • while (true) { • System.out.println("wait to client...."); • clientSocket = serverSocket.accept(); • thread = new Thread(new ServerThread(clientSocket)); • thread.start(); • } • } catch (IOException e) { • System.out.println("some error:" + e.getMessage()); • } • } • }
class ServerThread implements Runnable { • Socket clientSocket = null; • PrintStream out = null; • BufferedReader in = null; • public ServerThread(Socket s) { • this.clientSocket = s; • } • public void run() { • System.out.println("the client information :"+ clientSocket.getRemoteSocketAddress()); • try { • out = new PrintStream(clientSocket.getOutputStream()); • in = new BufferedReader(new InputStreamReader(clientSocket • .getInputStream())); • String str = in.readLine(); • System.out.println("client comes message:" + str); • out.println("I am Server"); • out.flush(); • out.close(); • in.close(); • clientSocket.close(); • } catch (IOException e) { • System.out.println("Error:"+e.getMessage()); • } • } • }
UDP SOCKET • Interface • DatagramSocketImplFactory • Class • java.net.DatagramPacket • java.net.DatagramSocket • java.net.DatagramSocketImpl • java.net.MulticastSocket • Exception • java.net.SocketException DatagramSocket DatagramPacket receive send close
UDP SOCKET • 與TCP的socket不同,UDP的socket只有DatagramSocket。 • 而傳送資訊的方式也大不相同,它是把資訊封裝在DatagramPacket,再把這個packet傳送出去。 • DatagramSocket也可以在廣播ip中發送廣播
UDP SOCKET • Encapsulation of data(packet) to be received/transmitted and related information. • // for receiving packets • DatagramPacket(byte[] data [ [, int offset] , int length]) • // for sending packets • DatagramPacket(byte[] data [ [, int offset], int length], InetAddress ia ,int port )
import java.io.*; import java.net.*; public class UDPClient { public static void main(String args[]) throws Exception { int portNo = 8888; BufferedReader uip = new BufferedReader( new InputStreamReader(System.in)); InetAddress addr = InetAddress.getByName("localhost"); System.out.print("please key the message to server :"); String msg = uip.readLine(); byte buffer[] = new byte[256]; buffer = msg.getBytes(); DatagramPacket packet = new DatagramPacket( buffer, buffer.length, addr,portNo); DatagramSocket socket = new DatagramSocket(); DatagramPacket dp = new DatagramPacket(new byte[256], 256); socket.send(packet); try { socket.receive(dp); String s = new String(dp.getData(), 0, dp.getLength()); System.out.println("the server comes message : [" + s + "]"); } catch (IOException ex) { System.err.println(ex); } socket.close(); } } send receive
import java.io.IOException; import java.net.*; public class EchoUDPServer { static final int BUFFERSIZE = 256; public static void main(String[] args) { DatagramSocket sock; DatagramPacket pack = new DatagramPacket( new byte[BUFFERSIZE],BUFFERSIZE); try { sock = new DatagramSocket(8888); } catch (SocketException e) { System.out.println(e); return; } // echo back everything try { sock.receive(pack); sock.send(pack); } catch (IOException ioe) { System.out.println(ioe); } sock.close(); } }