JAVA基礎知識|Socket
一、什麽是Socket?
Socket本身並不是協議,是一套完成TCP、UDP協議的調用接口(API),通過socket我們才能使用TCP/IP協議(JAVA基礎知識|TCP/IP協議)。Socket的出現只是使得程序員更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象,從而形成了我們知道的一些最基本的函數接口。
Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於服務器端,稱為ServerSocket 。
HTTP請求是基於Socket之上的(HTTP是轎車,提供了封裝或者顯示數據的具體形式;Socket是發動機,提供了網絡通信的能力。),總體來說, 只要是涉及到通訊類的應用,都是需要使用Socket, 最著名的就是我們常用的QQ、微信、旺旺等。
二、Socket通信過程
首先我們來看一下瀏覽器向Web服務器發出Http請求以及Web服務器給瀏覽器回復的過程:
1)瀏覽器創建Socket,按給定IP(域名)和端口(默認為80)連接服務器。比如使用類似Socket.Connect()、Socket.BeginConnect()等方法;
2)連接成功後,瀏覽器依據HTTP協議規範(關於協議,後面有講到),向Web服務器發送請求數據。比如“請求行”、“請求頭標”以及“請求數據”等,這裏可能使用類似Socket.Send()、Socket.BeginSend()等方法。
3)瀏覽器等待服務器處理並返回數據;
4)Web服務器端使用Socket.Accept()、Socket.BeginAccept()等方法偵聽到瀏覽器的連接後,便開始接收瀏覽器發送的數據。接收到請求數據後,依據HTTP協議規範解析數據,然後處理,最終將處理結果(如html文檔)發回給瀏覽器,這裏可能用到類似Socket.Send()、Socket.BeginSend()等方法;
5)Web服務器發送完處理結果後,關閉Socket;
6)瀏覽器接收Web服務器發回的數據(如html),將其顯示在瀏覽器UI界面。關閉socket;
7)一次“瀏覽器到Web服務器”的http請求結束;
8)下一次瀏覽器需要請求Web服務器,跳轉到第1)步循環開始。
用圖表示以上過程:
三、使用Socket模擬Web服務器
實際Web程序運行過程中,由瀏覽器創建Socket並與Web服務器進行連接,完成數據的交互與傳輸。下面我們使用代碼來模擬實現Web服務器接收Socket請求,並返回請求的過程。當然我們也可以模擬瀏覽器的功能,傳輸內容要符合http協議規定的格式。
IPAddress address = IPAddress.Loopback;//取得本機的loopback網絡地址,即127.0.0.1 IPEndPoint endPoint = new IPEndPoint(address, 49152);//創建可訪問的端點,49152表示端口號,如果設置為0,表示使用一個空閑的端口號 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//創建socket,使用IPv4地址,數據通信類型為字節流,TCP協議 socket.Bind(endPoint);//將socket綁定到一個端點上 socket.Listen(10);//設置連接隊列的長度 Console.WriteLine("開始監聽,端口號:{0}", endPoint.Port); while (true) { Socket client = socket.Accept();//開始監聽,這個方法會阻塞線程的執行,直到接受到一個客戶端的請求連接 Console.WriteLine(client.RemoteEndPoint);//輸出客戶端的地址 byte[] buffer = new byte[4096];//準備讀取客戶端請求的數據,讀取的數據將保存在一個數組中 int length = client.Receive(buffer, 4096, SocketFlags.None);//接受數據 //將請求數據翻譯為UTF-8 System.Text.Encoding utf8 = System.Text.Encoding.UTF8; string requestString = utf8.GetString(buffer, 0, length); Console.WriteLine(requestString);//顯示請求 //回應的狀態行 string statusLine = "HTTP/1.1 200 OK\r\n"; byte[] statusLineBytes = utf8.GetBytes(statusLine); //準備發送回客戶端的網頁 string responseBody = "<html><head><title>From Socket Server</title></head><body><h1>Hello world.<h1></body></html>"; byte[] responseBodyBytes = utf8.GetBytes(responseBody); //回應的頭部 string responseHeader = string.Format("Content-Type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n", responseBody.Length); byte[] responseHeaderBytes = utf8.GetBytes(responseHeader); //向客戶端發送狀態信息 client.Send(statusLineBytes); //向客戶端發送回應頭 client.Send(responseHeaderBytes); //頭部與內容的分隔行 client.Send(new byte[] { 13, 10 }); //向客戶端發送內容部分 client.Send(responseBodyBytes); //斷開與客戶端的連接 client.Close(); if (Console.KeyAvailable) break; } socket.Close();
JAVA基礎知識|Socket