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