一、 Socket的工做流程java
Socket實質上提供了進程通訊的端點。進程通訊以前,雙方首先必須各自建立一個端點,不然是沒有辦法創建聯繫並相互通訊的。正如打電話以前,雙方必須各自擁有一臺電話機同樣。linux
對於一個功能齊全的Socket,都要包含如下結構,其工做流程包含如下四個基本步驟:算法
(1) 建立Socket編程
(2) 打開鏈接到Socket的輸入/輸出流windows
(3) 按照必定的協議對Socket進行讀/寫操做服務器
(4) 關閉Socket多線程
二、 java中的Socketsocket
java中的socket通訊主要經過兩個已經封裝好的類ServerSocket和Socket性能
socket一般開發的是客戶端,用來讓客戶端經過端口號和IP地址鏈接到遠程服務器。而ServerSocket實現的則是一個服務器應用,ServerSocket會一直等待客戶端的請求,一旦得到了一個鏈接請求,就建立一個socket示例來與客戶端進行通訊。ServerSocket會綁定一個固定的端口,知曉此端口和遠程服務器的客服端能夠經過IP地址和端口號來與遠程客戶端通訊,而服務端的端口則是隨機的,在socket的應用中,咱們並不關心客戶端的端口號。測試
三、 實現
Java中的socket在底層實現時最終是經過調用系統的socket來實現的,下面是java中的socket類的繼承關係
從上圖中能夠看出ServerSocket就是針對SocketImpl的一個外觀類。SocketImple是一個抽象類,而且這個抽象類SocketImpl實現了SocketOptions接口。
SocketOptions接口中聲明的final屬性
SocketImpl中的屬性
四、 windows和Linux中的socket
windows在windows中socket方法返回的是SOCKET 一個宏定義
以下圖所示
從上方代碼看出他是u_int類型的別名,一個文件描述符爲何是int呢?由於在windows編程下主要使用的是句柄,而句柄就是一串int數字這個數字標識這一個內存中的類(這裏能夠理解在系統中是鍵值對而這個int則是key,而他獲取的對象則就是咱們使用accept或bind所須要的),暫時能夠這麼理解由於即便是內存也是鍵值對的map,各位讀者暫時將這個int當作一個key值而調用其餘socket方法都是須要這個key值的沒有這個key是操做不了的。
linux在linux中socket方法比windows要直接,他直接返回的是int類型
以下圖所示
上面都是針對linux和windows的講解那麼在java中是怎麼描述的呢?
上面的代碼是從SocketImpl中的bind方法的jni實現中的,能夠看出他先獲取了FileDescriptor對象也就是SocketImpl的fd,而後再根據FileDescriptor獲取到他的fd咱們最終使用的文件描述符,而文件描述符也是int類型的,因此在java中的socket方法返回的也是int類型。
五、java中的socket和Linux的socket的區別
Socket是winsock裏的原始套接字開發接口API,java是一門開發語言,而socket是一種通信標準的簡稱。Linux中的socket指的就是系統底層的socket,而像java這些開發語言,由於java自己是不帶有socket通信底層實現的,因此他們所使用的socket只不過是對系統底層的Socket API進行了二次封裝,面向開發人員,其本質上仍然和Linux底層的socket是同一個東西
六、java中的Socket用法
(1) Socket的構造
Socket() 經過系統默認類型的 SocketImpl 建立未鏈接套接字
Socket(InetAddress address, int port) 建立一個流套接字並將其鏈接到指定 IP 地址的指定端口號。
Socket(String host, int port)
Socket(String host, int port, InetAddress localAddr, int localPort) 建立一個套接字並將其鏈接到指定遠程主機上的指定遠程端口。
(2) 方法摘要
void |
bind(SocketAddress bindpoint) |
void |
close() |
void |
connect(SocketAddress endpoint) |
void |
connect(SocketAddress endpoint, int timeout) |
getChannel() |
|
getInetAddress() |
|
getInputStream() |
|
boolean |
getKeepAlive() |
getLocalAddress() |
|
int |
getLocalPort() |
getLocalSocketAddress() |
|
boolean |
getOOBInline() |
getOutputStream() |
|
int |
getPort() |
int |
getReceiveBufferSize() |
getRemoteSocketAddress() |
|
boolean |
getReuseAddress() |
int |
getSendBufferSize() |
int |
getSoLinger() |
int |
getSoTimeout() |
boolean |
getTcpNoDelay() |
int |
getTrafficClass() |
boolean |
isBound() |
boolean |
isClosed() |
boolean |
isConnected() |
boolean |
isInputShutdown() |
boolean |
isOutputShutdown() |
void |
sendUrgentData(int data) |
void |
setKeepAlive(boolean on) |
void |
setOOBInline(boolean on) |
void |
setPerformancePreferences(int connectionTime, int latency, int bandwidth) |
void |
setReceiveBufferSize(int size) |
void |
setReuseAddress(boolean on) |
void |
setSendBufferSize(int size) |
static void |
setSocketImplFactory(SocketImplFactory fac) |
void |
setSoLinger(boolean on, int linger) |
void |
setSoTimeout(int timeout) |
void |
setTcpNoDelay(boolean on) |
void |
setTrafficClass(int tc) |
void |
shutdownInput() |
void |
shutdownOutput() |
七、javasocket編程-簡單的hello/hi實現
基於服務器端實現的一個簡單的聊天機器人,可支持多人同時聊天
效果以下:
左邊的是聊天服務器,右邊兩個是客戶端
聊天恢復,第二個客戶端下線
代碼實現:
Demo_Receive.java:
Demo_Send.java:
Java中實現多線程主要有兩種方法:
一、 繼承Thread類,重寫run()方法
二、 實現Runnable接口,重寫Run()方法
這裏使用的是第二種方法
做者:
SA19225475
參考:
https://www.jianshu.com/p/83d5598b9d3b java中socket的實現
https://blog.csdn.net/weixin_34220834/article/details/85747263
JAVA Socket編程和C++ Socket編程有什麼不一樣
https://blog.csdn.net/weixin_33829657/article/details/92413466
JAVA中的socket的繼承關係