套接字(socket)是通信的基石,套接字鏈接需要五個(gè)元素:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)程主機(jī)的 IP地址,遠(yuǎn)程主機(jī)的協(xié)議端口;
套接字(Socket)連接需要的三個(gè)步驟:1.服務(wù)器監(jiān)聽,2.客戶端請(qǐng)求,3.連接確認(rèn);
套接字(Socket)連接的作用:應(yīng)用層通過傳輸層進(jìn)行通信時(shí),TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序提供并發(fā)服務(wù)的問題,多個(gè)TCP連接或多個(gè)應(yīng)用程序可能會(huì)同時(shí)使用同一個(gè)協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)分不同運(yùn)用程序和連接,操作系統(tǒng)為應(yīng)用程序和TCP/IP協(xié)議提供了套接字(Socket)接口應(yīng)用層和傳輸層可以通過Socket接口,區(qū)分來自不同應(yīng)用程序和網(wǎng)絡(luò)通信的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
示例:
//server,本例服務(wù)器與客戶端都在本機(jī),使用8888端口,本地ip:127.0.0.1
Map<Socket,ObjectOutputStream> soosMap ;
Map<Socket,ObjectInputStream> sois;
ServerSocket ss = new ServerSocket(8888);
while(true){
Socket s = ss.accept();//socket通信是阻塞的,當(dāng)沒有接收到ClientSocket連接請(qǐng)求時(shí),程序一直阻塞,不向下執(zhí)行,直到收到連接請(qǐng)求
ObjectOutputStream oos = new ObjectOutputStream();
soosMap.put(s,oos);//為每一個(gè)客戶端產(chǎn)生一個(gè)輸出流,進(jìn)行通信,同樣的,客戶端也有一個(gè)輸入流用于通信;在客戶端也創(chuàng)建一個(gè)輸入流來接受服務(wù)器發(fā)出的消息
new AcceptMessageThread(s).start();//消息監(jiān)聽線程一直監(jiān)聽客戶端,等待消息通信;
}
Thread AcceptMessageThread extends Thread{
private Socket s;
public AcceptMessageThread(Socket s){
this.s = s;
}
public void run(){
ObjectInputStream ois = new ObjectInputStream(s.getInputStream);//為每一個(gè)socket連接對(duì)象創(chuàng)建一個(gè)對(duì)象輸入流來接收客戶端的通信消息,在客戶端也同樣創(chuàng)建一個(gè)輸出流來發(fā)送消息
while(true){//保持監(jiān)聽
Message msg = ois.readObject();
}
}
}
//Client
private Socket s;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private void initClient() {
while(true){
try {
s =new Socket("127.0.0.1",8888);
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
break;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}