socket编程学习笔记
socket編程:
1、網絡基礎知識
兩臺計算機通過網絡進行通信,首先兩臺計算機要有唯一的標識,即唯一的IP地址。其次他們要有共同的語言用來交流即協議。再者,每套主機要有相應的端口號。
TCP/IP協議:
--TCP/IP協議是目前世界上應用最為廣泛的協議,是以TCP和IP為基礎的不同層次上多個協議的集合,也稱:TCP/IP協議族 或 TCP/IP協議棧
--TCP的全稱:Transmission Control Protocol 傳輸控制協議
--IP的全稱:Internet Protocol 互聯網協議
TCP/IP模型
一般分為五層:
5-應用層:HTTP 超文件傳輸協議 FTP 文件傳輸協議 SMTP 簡單郵件傳送協議 Telnet遠程登錄服務
4-傳輸層:TCP/IP協議
3-網絡層
2-數據鏈路層
1-物理層:網線,雙絞線,網卡
IP地址---《探索Linux的網絡世界》為實現網絡中不同計算機之間的通信,每臺機器都必須有一個唯一的標識---IP地址
IP地址格式:數字型,如:192.168.0.1
IP地址的長度:32位的二進制
端口
端口號
1、用于區分不同應用程序
2、端口號范圍為0~65535,其中0~1023為系統所保留
3、IP地址和端口號就組成了所謂的Socket,Socket是網絡上運行的程序之間雙向通信鏈路的終結點,是TCP和UDP的基礎。
4、常見的一些協議使用的端口號
http:80 ftp:21 telnet:23
Java中的網絡支持
針對網絡通信的不同層次,Java提供的網絡功能有四大類:
1、InetAddress類:用于標識網絡上的硬件資源。
2、URL:統一資源定位符 通過URL可以直接讀取或寫入網絡上的數據。
3、Sockets(TCP編程):使用TCP協議實現網絡通信的Socket相關的類。
4、Datagram(UDP編程):使用UDP協議,將數據保存在數據報中,通過網絡進行通信。
2、InetAdress類
java.net.InetAddress
所有已實現的接口:Serializable
直接已知子類:Inet4Address,Inet6Address
沒有構造方法。
(1)InetAddress類用于標識網絡上的硬件資源,表示互聯網協議(IP)地址。
栗子又來啦!!!
會輸出計算機名,IP地址,以及字節數組形式的IP。
輸出:(計算機名純屬自己杜撰,如有雷同,純屬巧合,IP地址也是)
計算機名:MyTeam
IP地址:192.16.54.161
字節數組形式的IP:[-80,16,54,-70]
MyTeam/192.16.54.161
計算機名:MyTeam.it2102.fhjd.com.cn
IP地址:192.16.54.161
3、URL
3-1、URL(Uniform Resource Locator)統一資源定位符,表示Internet上某一資源的地址
小栗子來理解url的常用方法:
3-2、使用URL讀取網頁內容
1、通過URL對象的openStream()方法可以得到指定資源的輸入流。
2、通過流來讀取、訪問網絡上的數據。
!!!看這里
4、Socket通信
TCP協議是面向連接、可靠的、有序的、以字節流的方式發送數據。
基于TCP協議實現網絡通信的類:客戶端的Socket類,服務器端的ServerSocket類
Socket通信模型
Server
建立服務器傾聽socket ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Client
等待并接收連接請求------------建立連接---------創建連接socket向服務端發送請求
接收請求后創建連接socket
--------------------------------------------------------------------------------------------------------------------
InputStream----------------------------------------------OutputStream
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 開始通信
OutputStream-------------------------------------------InputStream
-------------------------------------------------------------------------------------------------------------------
關閉socket及相關資源--------結束通信-------------關閉socket及相關資源
Socket通信實現步驟
1、分別在服務器端和客戶端創建ServerSocket和Socket
2、打開連接到Socket的輸入/輸出流,進行數據通信
3、按照協議對Socket進行讀/寫操作
4、關閉輸入輸出流,關閉Socket
ServerSocket:
ServerSocket類位于java.net包中,直接已知子類是SQLServerSocket,此類實現服務器套接字。
服務器套接字等待請求通過網絡傳入。它基于該請求執行某些操作,然后可能向請求者返回結果。
服務器套接字的實際工作由SocketImpl類的實例執行。應用程序可以更改創建套接字實現的套接字工廠來配置它自身,從而創建適合本地防火墻的套接字。
構造方法:
ServerSocket(int port)----創建綁定到特定端口的服務器套接字。
方法摘要:
accept()-----偵聽并接受到此套接字的連接。
bind()-------將ServerSocket綁定到特定地址(IP地址和端口號)
close()------關閉此套接字。
getChannel()------返回與此套接字關聯的唯一ServerSocketChannel對象(如果有)
getInetAddress()------返回此服務器套接字的本地地址。
getLocalPort()--------返回此套接字在其上偵聽的端口。
getLocalSocketAddress()----返回此套接字綁定的端點的地址,如果尚未綁定則返回null。
getReceiveBufferSize()---獲取此ServerSocket的SO_RCVBUF選項的值,該值是將用于從此ServerSocket接受的套接字的建議緩沖區大小。
Socket:
位于java.net包中,直接已知子類是:SSLSocket,此類實現客戶端套接字(也可以就叫“套接字”)。套接字
是兩臺機器間通信的端點。
套接字的實際工作由SocketImpl類的實例執行。應用程序通過更改創建套接字實現的套接字工廠可以配置它自身,創建適合本地防火墻的套接字。
構造方法:
Socket(InetAddress address,int port)----創建一個流套接字并將其連接到指定IP地址的指定端口號。
Socket(String host,int port)-----創建一個流套接字并將其連接到指定主機上的指定端口號。
方法摘要:
bind(SocketAddress bindpoint)---將套接字綁定到本地地址。
close()-----關閉此套接字。
connect(SocketAddress endpoint,int timeout)------將此套接字連接至服務器,并制定一個超時值。
getChannel()--------返回與此數據報套接字關聯的唯一的SocketChannel對象(如果有)。
getInetAddress()-----返回套接字連接的地址。
getInputStream()-----返回此套接字的輸入流。
getKeepAlive()-------測試是否啟用SO_KEEPALIVE.
shutdownInput()------此套接字的輸入流置于“流的末尾”。
shutdownOutput()------禁用此套接字的輸出流。
實現用戶登錄的步驟:
基于TCP協議的Socket通信,實現用戶登錄
服務器端:
客戶端:
1 import java.net.Socket; 2 import java.net.IOException; 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.io.PrintWriter; 8 import java.net.UnknownHostException; 9 public class Client{ 10 public static void main(String[] args){ 11 try{ 12 //1、創建客戶端Socket,指定服務器地址和端口 13 Socket socket=new Socket("localhost",8888); 14 //2、獲取輸出流,向服務器端發送信息 15 OutputStream os=socket.getOutputStream();//字節輸出流 16 PrintWriter pw=new PrintWriter(os);//將輸出流包裝為打印流 17 pw.write("用戶名:admin;密碼:123"); 18 pw.flush(); 19 socket.shutdownOutput();//關閉輸出流 20 //3、獲取輸入流,并讀取服務器端的響應信息 21 InputStream is=socket.getInputStream(); 22 BufferedReader br=new BufferedReader(new InputStreamReader(is));//將字節流包裝為字符流 23 String info=null; 24 while((info=br.readLine())!=null){ 25 System.out.println("我是客戶端,服務器說:"+info); 26 } 27 //4、關閉資源 28 br.close(); 29 is.close(); 30 pw.close(); 31 os.close(); 32 socket.close(); 33 }catch(UnknownHostException e){ 34 e.printStackTrace(); 35 }catch(IOException e){ 36 e.printlnStackTrace(); 37 } 38 } 39 }注:服務器必須早于客戶端啟動
5、使用多線程實現多客戶端的通信
基本步驟:
1、服務器端創建ServerSocket,循環調用accept()等待客戶端連接
2、客戶端創建一個socket并請求和服務器端連接
3、服務器端接受客戶端請求,創建socket與該客戶建立專線連接
4、創建連接的兩個socket在一個單獨的線程上對話
5、服務器端繼續等待新的連接
服務器線程處理類:
服務器端:
1 import java.net.ServerSocket; 2 import java.net.Socket; 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.io.IOException; 6 import java.io.OutputStream; 7 import java.io.PrintWriter; 8 public class Server{ 9 public static void main(String[] args){ 10 try{ 11 //1、創建一個服務器端Socket,即ServerSocket,指定綁定的端口,并監聽此端口 12 ServerSocket serverSocket=new ServerSocket(8888); 13 Socket socket=null; 14 //記錄客戶端的數量 15 int count=0; 16 System.out.println("***服務器即將啟動,等待客戶端的連接***"); 17 //循環監聽等待客戶端的連接 18 while(true){ 19 //調用accept()方法開始監聽,等待客戶端的連接 20 socket=serverSocket.accept(); 21 //啟動一個線程,通過當前線程與客戶端進行通信 22 ServerThread serverThread=new ServerThread(socket); 23 //啟動線程 24 serverThread.start(); 25 26 count++;//統計客戶端的數量 27 System.out.println("客戶端的數量:"+count); 28 InetAddress address=socket.getInetAddress(); 29 System.out.println("當前客戶端的IP:")+address.getHostAddress()); 30 } 31 }catch(IOException e){ 32 e.printStackTrace(); 33 } 34 } 35 }?
客戶端:
1 import java.net.Socket; 2 import java.net.IOException; 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.io.PrintWriter; 8 import java.net.UnknownHostException; 9 public class Client{ 10 public static void main(String[] args){ 11 try{ 12 //1、創建客戶端Socket,指定服務器地址和端口 13 Socket socket=new Socket("localhost",8888); 14 //2、獲取輸出流,向服務器端發送信息 15 OutputStream os=socket.getOutputStream();//字節輸出流 16 PrintWriter pw=new PrintWriter(os);//將輸出流包裝為打印流 17 //模擬多客戶端同時登錄 18 pw.write("用戶名:admin;密碼:123"); 19 //pw.write("用戶名:er;密碼:456"); 20 pw.flush(); 21 socket.shutdownOutput();//關閉輸出流 22 //3、獲取輸入流,并讀取服務器端的響應信息 23 InputStream is=socket.getInputStream(); 24 BufferedReader br=new BufferedReader(new InputStreamReader(is));//將字節流包裝為字符流 25 String info=null; 26 while((info=br.readLine())!=null){ 27 System.out.println("我是客戶端,服務器說:"+info); 28 } 29 //4、關閉資源 30 br.close(); 31 is.close(); 32 pw.close(); 33 os.close(); 34 socket.close(); 35 }catch(UnknownHostException e){ 36 e.printStackTrace(); 37 }catch(IOException e){ 38 e.printlnStackTrace(); 39 } 40 } 41 }6、基于UDP的socket編程
UDP協議(用戶數據報協議)是無連接的、不可靠的、無序的。
UDP協議以數據報作為數據傳輸的載體
使用UDP進行數據傳輸時,首先需要將要傳輸的數據定義成數據報(Datagram),在數據報中指明數據所要達到的Socket(主機地址和端口號),然后再將數據報發送出去。
相關操作類:
DatagramPacket:表示數據報包,數據報包用來實現無連接包投遞服務。每條報文僅根據該包中包含的信息從一臺機器路由器。從一臺機器發送到另一臺機器的多個包可能選擇不同的路由,也可能按不同的順序傳遞做出保證。
構造方法摘要:
DatagramPacket(byte[] buf, int length):構造DatagramPacket,用來接收長度為length的數據包。
DatagramPacket(byte[] buf,int length,InetAddress address,int port):構造數據報包,用來將長度為length的包發送至指定主機上的指定端口號。
DatagramPacket(byte[] buf,int offset,int length):構造DatagramPacket,用來接收長度為length的包,在緩沖區指定了偏移量為offset
DatagramSocket:進行端到端通信的類,表示用來發送和接收數據報包的套接字。
數據報套接字是包投遞服務的發送或接收點。每個在數據報套接字上發送或接收的包都是自由的。從一臺機器發送到另一臺機器的多個包可能選擇不同的路由,也可能按不同的順序。
構造方法摘要:
DatagramSocket():構造數據報套接字并將其綁定到本地主機上任何可用的端口。
DatagramSocket(DatagramSocketImpl impl):創建帶有指定DatagramSocketImpl的未綁定數據報套接字。
DatagramSocket(int port,InetAddress laddr):創建數據報套接字,將其綁定到指定的本地地址。
方法摘要:
close():關閉此數據報套接字。
bind():將此DatagramSocket綁定到特定的地址和端口。
getLocalAddress():返回此套接字連接的地址
getpPort():返回此套接字的端口
send():從此套接字發送數據報包
receive():從此套接字接收數據報包
基于UDP的用戶登錄:
服務器端實現步驟:
客戶端實現步驟:
1 import java.net.DatagramSocket; 2 import java.net.DatagramPacket; 3 import java.net.InetAddress; 4 import java.io.IOException; 5 6 public class UDPClient{ 7 /* 8 *向服務器端發送請求 9 */ 10 public static void main(String[] args) throws IOException{ 11 //1、定義服務器的地址、端口號、數據 12 InetAddress address=InetAddress.getByName("localhost"); 13 int port=8800; 14 byte[] data="用戶名:admin;密碼:123".getBytes(); 15 //2、創建數據報,包含發送的數據信息 16 DatagramPacket packet packet=new DatagramPacket(data,data.length,address,port) 17 //3、創建DatagramSocket對象 18 DatagramSocket socket=new DatagramSocket(); 19 //4、向服務器端發送數據報 20 socket.send(packect); 21 22 /* 23 *接收服務器端響應的數據 24 */ 25 //1、創建數據報,用于接收服務器端響應的數據 26 byte[] data2=new byte[1024]; 27 DatagramPacket packet2=new DatagramPacket(data2,data.length); 28 //2、接受服務器響應的數據 29 socket.receive(packet2); 30 //3、讀取數據 31 String reply=new String(data2,0,packet2.getLength()); 32 System.out.println("我是客戶端,服務器說:"+reply); 33 //4、關閉資源 34 socket.close(); 35 } 36 }重點:Socket通信,基于TCP的Socket通信
經驗和技巧:
多線程的優先級,是否關閉輸入流和輸出流,使用TCP通信傳輸對象,socket編程傳遞文件
?
?
轉載于:https://www.cnblogs.com/gree/p/8821750.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的socket编程学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: codemirror实现SQL代码自动提
- 下一篇: python内置支持集合运算吗_Pyth