最近一個項目中接口通訊這一塊主要是調用銀聯系統的socket接口,我方是客戶端,即發送請求接收返回報文的一方。在貼代碼之前,還是要了解一下關于socket的基礎知識。
Socket的基本概念
1.建立連接
當需要建立網絡連接時,必須有一臺機器運行一個程序,隨時等候連接,而另一端的程序這對其發出連接請求。這一點同電話系統類似——必須有一方撥打電話,而另一方必須等候電話連通。
建立連接的過程為:
(1)先在服務器端生成一個ServerSocket實例對象,隨時監聽客戶端的連接請求。
(2)當客戶端需要連接服務端時,相應地要生成一個Socket實例對象,并發出連接請求,其中host參數指明該主機名,port參數指明該主機端口號。
(3)服務器端通過accept()方法接收到客戶端的請求后,開辟一個接口與之進行連接,并生成所需的I/O數據流。
(4)客戶端和服務器端的通信都是通過一對InputStream和OutputStream進行的,通信結束后,兩端分別關閉對應的Socket接口。
2.連接地址
打電話時,呼叫方必須事先知道所需撥打的號碼,而程序建立網絡連接時,也同樣需要知道地址或主機名稱。
另外,網絡連接還需要一個端口號(可以將其當作電話的分機號),連接到正確的主機之后,需要對該連接確認特定口令。
3.端口號
在TCP/IP系統中,端口號由16位二進制整數組成,即在0-65535之間。實際應用中,前1024個端口號已經預先定義為一些特定服務,因此一般不能使用,除非想同這些服務器進行連接(如Telnet,SMTP,mail,ftp等)。在兩個程序連接之前,彼此之間必須達成一致,即由客戶端負責初始化連接,而服務器隨時等候請求。只有客戶端和服務器端指定端口號一致時連接才會建立。如果系統中兩個程序所用端口號不一致,這連接無法建立。
4.網絡連接模式
在Java中,TCP/IP接口的連接是由java.net包中的類實現的。如圖表示的是Socket連接過程中客戶端和服務器端的工作原理。
每個server端都擁有一個端口號,一臺機器上如果運行多個服務,這可能對應多個端口號。通信結束后,兩端分別關閉對應的Socket接口,而不影響其他的端口。
Socket通信的基本步驟
使用Socket方式進行網絡通信的程序基本結構都是類似的,無論一個Socket通信程序的功能多么齊全、程序多么復雜,其基本結構都是一樣的。客戶端與服務器端進行通信的過程都包括以下四個基本步驟:
(1)在服務器端指定一個用來等待連接的端口號,在客戶端規定一個主機和端口號,從而在客戶端和服務器端創建Socket/ServerSocket實例。
(2)打開連接到Socket的輸入輸出流。
(3)利用輸入輸出流,按照一定的協議對Socket進行讀寫操作。
(4)關閉輸入輸出流和Socket
通常,程序員的主要工作時針對所要完成的功能砸器第(3)步進行編程,第(1)、(2)、(4)步對所有的通信程序來說幾乎都是一樣的。
Socket類中常用的構造函數
1:Socket(InetAddress address,int port) :該方法用于創建一個鏈接,向指定的IP地址上指定的端口的服務器端程序發送連接請求
2:Socket(InetAddress address,int port) :?同上,但該方法允許通過主機名字符串向服務器發送連接請求
Socket類中常用的方法
1:InetAddress getLocalAddress() :返回和Socket進行連接的本地的IP地址
2:int getLocalPort() :返回和Socket進行連接的本地的端口號
3:InetAddress getInetAddress():返回Socket建立了連接的服務器的IP地址
4:int getPort():返回和Socket建立了連接的服務器的端口號
5:InputStream getInputStream() :返回當前Socket的輸入流(常用)
6:OutputStream getOutStream():返回當前Socket的輸出流(常用)
7:void close():關閉當前的Socket 連接
ServerSocket中常用的構造函數
1:ServerSocket(int port) :這是構造方法用于在當前的服務器默認的IP地址上監聽一個指定的端口,即在指定的IP和端口創建一個ServerSocket對象
ServerSocket中常用的方法
1:Socket accept() :產生阻塞,監聽指定的端口,直至有客戶端發來連接請求(常用)
2:void close() :關閉當前ServerSocket
3:InetAddress getInetAddress() :返回ServerSocket監聽的本機的IP地址
4:int getLocalPort(): 返回ServerSocket監聽的,本機的IP地址上指定的端口號
5:int getSoTimeout()::void setSoTimeout(int timeout) 設置連接過程中沒有得到相應的等待期限時間(TimeOut)
6:String toString() : 以字符串的方式返回ServerSocket監聽的,本機的IP地址及其端口號
Socker通信的程序設計
終于到了貼代碼的時間了。。。。。
1.服務器端程序
public static voidmain(String[] args) {//定義ServerSocket和Socket對象
ServerSocket ss = null;
Socket sk;//定義發送字符串,即客戶端收到的信息
String sendString = "hello!我是服務端...";//定義OutputStream類
OutputStream s1out;//定義DataOutputStream類
DataOutputStream dos;//通過1314端口建立連接
try{//創建ServerSocket并把傳入端口號
ss = new ServerSocket(1314);
}catch(Exception e) {
e.printStackTrace();
}//循環運行監聽程序,以監視連接請求
while (true) {try{//監聽端口請求,等待連接
sk =ss.accept();//得到與socket相連接的數據流對象
s1out =sk.getOutputStream();
dos= newDataOutputStream(s1out);//發送字符串
dos.writeUTF(sendString);//關閉數據流(但不是關閉Socket連接)
dos.close();
s1out.close();
sk.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
2.客戶端程序
/*** 采用socket連接向服務器發送消息,接受響應信息 注意,如果是通過不同的ip port確定調用接口 這個方法要重寫,將ip
* port作為請求條件,現改為傳固有參數進來
*
*@paramtext
*@throwsException*/
public staticString sendBySocket(String text, String ip, int port)throwsException {log.info("開始建立socket連接");
Socket socket= newSocket(ip, port);
InputStream is=socket.getInputStream();
InputStreamReader isr= new InputStreamReader(is, "GBK");//2.獲取客戶端輸出流
OutputStream dos =socket.getOutputStream();
log.info("連上服務端");//3.向服務端發送消息
dos.write(text.getBytes());
dos.flush();
log.info("成功向服務器發送消息");//4.獲取輸入流,并讀取服務器端的響應信息
BufferedReader br = newBufferedReader(isr);
String returnInfo=br.readLine();
log.info("服務器端返回數據為:" +returnInfo);//4.關閉資源
br.close();
isr.close();
is.close();
dos.close();
socket.close();returnreturnInfo;
}