基於java實現的一個hello/hi的簡單的網絡聊天程序

一、  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)
          將此套接字鏈接到服務器,並指定一個超時值。

 SocketChannel

getChannel()
          返回與此數據報套接字關聯的惟一 SocketChannel 對象(若是有)。

 InetAddress

getInetAddress()
          返回套接字鏈接的地址。

 InputStream

getInputStream()
          返回此套接字的輸入流。

 boolean

getKeepAlive()
          測試是否啓用 SO_KEEPALIVE。

 InetAddress

getLocalAddress()
          獲取套接字綁定的本地地址。

 int

getLocalPort()
          返回此套接字綁定到的本地端口。

 SocketAddress

getLocalSocketAddress()
          返回此套接字綁定的端點的地址,若是還沒有綁定則返回 null。

 boolean

getOOBInline()
          測試是否啓用 OOBINLINE。

 OutputStream

getOutputStream()
          返回此套接字的輸出流。

 int

getPort()
          返回此套接字鏈接到的遠程端口。

 int

getReceiveBufferSize()
          獲取此 Socket 的 SO_RCVBUF 選項的值,該值是平臺在 Socket 上輸入時使用的緩衝區大小。

 SocketAddress

getRemoteSocketAddress()
          返回此套接字鏈接的端點的地址,若是未鏈接則返回 null。

 boolean

getReuseAddress()
          測試是否啓用 SO_REUSEADDR。

 int

getSendBufferSize()
          獲取此 Socket 的 SO_SNDBUF 選項的值,該值是平臺在 Socket 上輸出時使用的緩衝區大小。

 int

getSoLinger()
          返回 SO_LINGER 的設置。

 int

getSoTimeout()
          返回 SO_TIMEOUT 的設置。

 boolean

getTcpNoDelay()
          測試是否啓用 TCP_NODELAY。

 int

getTrafficClass()
          爲今後 Socket 上發送的包獲取 IP 頭中的流量類別或服務類型。

 boolean

isBound()
          返回套接字的綁定狀態。

 boolean

isClosed()
          返回套接字的關閉狀態。

 boolean

isConnected()
          返回套接字的鏈接狀態。

 boolean

isInputShutdown()
          返回是否關閉套接字鏈接的半讀狀態 (read-half)。

 boolean

isOutputShutdown()
          返回是否關閉套接字鏈接的半寫狀態 (write-half)。

 void

sendUrgentData(int data)
          在套接字上發送一個緊急數據字節。

 void

setKeepAlive(boolean on)
          啓用/禁用 SO_KEEPALIVE。

 void

setOOBInline(boolean on)
          啓用/禁用 OOBINLINE(TCP 緊急數據的接收者) 默認狀況下,此選項是禁用的,即在套接字上接收的 TCP 緊急數據被靜默丟棄。

 void

setPerformancePreferences(int connectionTime, int latency, int bandwidth)
          設置此套接字的性能偏好。

 void

setReceiveBufferSize(int size)
          將此 Socket 的 SO_RCVBUF 選項設置爲指定的值。

 void

setReuseAddress(boolean on)
          啓用/禁用 SO_REUSEADDR 套接字選項。

 void

setSendBufferSize(int size)
          將此 Socket 的 SO_SNDBUF 選項設置爲指定的值。

static void

setSocketImplFactory(SocketImplFactory fac)
          爲應用程序設置客戶端套接字實現工廠。

 void

setSoLinger(boolean on, int linger)
          啓用/禁用具備指定逗留時間(以秒爲單位)的 SO_LINGER。

 void

setSoTimeout(int timeout)
          啓用/禁用帶有指定超時值的 SO_TIMEOUT,以毫秒爲單位。

 void

setTcpNoDelay(boolean on)
          啓用/禁用 TCP_NODELAY(啓用/禁用 Nagle 算法)。

 void

setTrafficClass(int tc)
          爲今後 Socket 上發送的包在 IP 頭中設置流量類別 (traffic class) 或服務類型八位組 (type-of-service octet)。

 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的繼承關係

相關文章
相關標籤/搜索