mysal向一个无法连接的网络尝试了一个套接字操作 0.0.3.235_第十二章 Java网络编程(3)——套接字(上)...
套接字
套接字概述
網(wǎng)絡通信使用IP地址標識Internet上的計算機,使用端口號標識服務器上的進程(程序)。也就是說,如果服務器上的一個程序不占用一個端口號,用戶程序就無法找到它,就無法和該程序交互信息。端口號規(guī)定為一個16位的0-65535之間的整數(shù),其中,0~1023被預先定義的服務通信占用(如telnet占用端口23,http占用端口80等),除非需要訪問這些特定服務,否則,就應該使用1024-65535這些端口中的某一個進行通信,以免發(fā)生端口沖突。
當兩個程序需要通信時,它們可以通過使用Socket 類建立套接字對象并連接在一起(端口號與IP地址的組合得出一個網(wǎng)絡套接字),本節(jié)將講解怎樣將客戶端和服務器端的套接字對象連接在一起來交互信息。
熟悉生活中的一些常識對于學習、理解以下套接字的講解是非常有幫助的,比如,有人讓你去“中關村郵局”,你可能反問“我去做什么”,因為他沒有告知你“端口”,你覺得不知處理何種業(yè)務。他說:“中關村郵局,8號窗口”,那么你到達地址“中關村郵局”,找到“8號”窗口,就知道8號窗口處理特快專遞業(yè)務,而且,必須有個先決條件,就是你到達“中關村郵局,8號窗口”時,該窗口必須有一位業(yè)務員在等待客戶,否則就無法建立交互業(yè)務。
客戶端套接字
客戶端程序使用Socket類建立負責連接到服務器的套接字對象。
Socket的構造方法是Socket (String host, int port),參數(shù)host是服務器的IP地址,port是一個端口號。建立套接字對象可能發(fā)生IOException異常,因此應像下面那樣建立連接到服務器的套接字對象:
try { Socket clientSocket = new Socket("http://192.168.0.78",2010); } catch (IOException e) {}當套接字對象clientSocket建立后,clientSocket可以使用方法getInputStream()獲得一個輸入流,這個輸入流的源和服務器端的一個輸出流的目的地剛好相同,因此客戶端用輸入流可以讀取服務器寫入到輸出流中的數(shù)據(jù);clientSocket使用方法getOutputStream()獲得一個輸出流,這個輸出流的目的地和服務器端的一個輸入流的源剛好相同,因此服務器用輸入流可以讀取客戶寫入到輸出流中的數(shù)據(jù)。
ServerSocket對象
與服務器端套接字
我們已經(jīng)知道客戶負責建立連接到服務器的套接字對象,即客戶負責呼叫。為了能使客戶成功地連接到服務器,服務器必須建立一個ServerSocket對象(像生活中郵局窗口的業(yè)務員),該對象通過將客戶端的套接字對象和服務器端的一個套接字對象連接起來,從而達到連接的目的。
ServerSocket的構造方法是ServerSocket (int port),port是一個端口號。port必須和客戶呼叫的端口號相同。當建立ServerSocket對象時可能發(fā)生IOException異常,因此應像下面那樣建立ServerSocket對象。
try { ServerSocket serverForClient = new ServerSocket(2010); } catch(IOException e) {}比如,2010端口已被占用時,就會發(fā)生IOException異常。
當服務器的ServerSocket對象serverForClient建立后,就可以使用方法accept()將客戶端的套接字和服務器端的套接字連接起來,代碼如下所示。
try { Socket sc = serverForClient.accept(); } catch(IOException e) {}所謂“接收”客戶的套接字連接是指serverForClient(服務器端的ServerSocket對象)調用accept()方法會返回一個和客戶端Socket對象相連接的Socket對象sc,sc駐留在服務器端,這個Socket對象sc調用getOutputStream()獲得的輸出流將指向客戶端Socket對象的輸入流,即服務器端的輸出流的目的地和客戶端輸入流的源剛好相同;同樣,服務器端的這個Socket對象sc調用getlnputStream()獲得的輸入流將指向客戶端Socket對象的輸出流,即服務器端的輸入流的源和客戶端輸出流的目的地剛好相同。因此,當服務器向輸出流寫入信息時,客戶端通過相應的輸入流就能讀取,反之亦然,如下圖所示。
需要注意的是,從套接字連接中讀取數(shù)據(jù)與從文件中讀取數(shù)據(jù)有著很大的不同,盡管二者都是輸入流。從文件中讀取數(shù)據(jù)時,所有的數(shù)據(jù)都已經(jīng)在文件中了。而使用套接字連接時,可能在另一端數(shù)據(jù)發(fā)送之前,就已經(jīng)開始讀取了,這時,就會阻塞本線程,直到該讀取方法成功讀取到信息,本線程才繼續(xù)執(zhí)行后續(xù)的操作。
另外,需要注意的是accept方法也會阻塞線程的執(zhí)行,直到接收到客戶的呼叫。也就是說,如果沒有客戶呼叫服務器,那么下述代碼中的System.out.println("hello");不會被執(zhí)行。
try { Socket sc= serverForClient.accept(); System.out.println("hello"); } catch(IOException e) {}連接建立后,服務器端的套接字對象調用getInetAddress()方法可以獲取一個InetAddess對象,該對象含有客戶端的IP地址和域名,同樣,客戶端的套接字對象調用getlnetAddress()方法可以獲取一個InetAddess對象,該對象含有服務器端的IP地址和域名。
雙方通信完畢后,套接字應使用close()方法關閉套接字連接。
注:ServerSocket對象可以調用setSoTimeout(int timeout)方法設置超時值(單位是毫秒),timeout是一個正值,當ServerSocket對象調用accept方法阻塞的時間一旦超過timeout時,將觸發(fā)SocketTimeoutException。
下面通過一個簡單的例子說明上面講的套接字連接。在例子3中,客戶端向服務器端問了三句話,服務器都一一給出了回答。首先將例子3中服務器端的Server.java編譯通過,并運行起來,等待客戶的呼叫,然后運行客戶端程序。程序代碼如下所示:
①客戶端
import java.io.*;import java.net.Socket;public class Client { public static void main(String[] args) { String [] mess = {"2010世界杯在哪舉行?","巴西進入世界杯了嗎?","中國進入世界杯了嗎?"}; Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket("127.0.0.1",2010); in= new DataInputStream(mysocket.getInputStream()); out = new DataOutputStream (mysocket.getOutputStream()); for(int i=0;i out.writeUTF(mess[i]); String s=in.readUTF(); //in讀取信息,阻塞狀態(tài) System.out.println("客戶收到服務器的回答:"+s); Thread.sleep(500); } } catch (Exception e) { System.out.println("服務器已斷開"+e); } }}②服務器端
import java.io.*;import java.net.*;public class Server { public static void main(String[] args) { String [] answer = {"南非","進入世界杯了","哈哈……問題真逗!"}; ServerSocket serverForClient = null; Socket socketOnServer = null; DataOutputStream out = null; DataInputStream in = null; try { serverForClient = new ServerSocket(2010); } catch (IOException el) { System.out.println(el); } try { System.out.println("等待客戶呼叫"); socketOnServer = serverForClient.accept(); //阻塞狀態(tài),除非有客戶呼叫 out = new DataOutputStream(socketOnServer.getOutputStream()); in = new DataInputStream(socketOnServer.getInputStream()); for(int i=0;i String s = in.readUTF(); //in讀取信息,阻塞狀態(tài) System.out.println("服務器收到客戶的提問:"+s); out.writeUTF(answer[i]); Thread.sleep(500); } } catch (Exception e) { System.out.println("客戶已斷開"+e); } }}客戶端運行效果如圖所示:
服務器端運行效果如圖所示:
總結
以上是生活随笔為你收集整理的mysal向一个无法连接的网络尝试了一个套接字操作 0.0.3.235_第十二章 Java网络编程(3)——套接字(上)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红小豆最晚什么时候种?
- 下一篇: 咖喱粉的生熟比例是多少?