網路上的兩個程式通過一個雙向的通信連線實現數據的交換,這個連線的一端稱為一個socket。
建立網路通信連線至少要一對連線埠號(socket)。socket本質是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程式設計師做網路開發所用的接口,這就是Socket編程接口;HTTP是轎車,提供了封裝或者顯示數據的具體形式;Socket是發動機,提供了網路通信的能力。
Socket的英文原義是“孔”或“插座”。作為BSD UNIX的進程通信機制,取後一種意思。通常也稱作"套接字",用於描述IP位址和連線埠,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在Internet上的主機一般運行了多個服務軟體,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個連線埠上,不同的連線埠對應於不同的服務。Socket正如其英文原義那樣,像一個多孔插座。一台主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟體將插頭插到不同編號的插座,就可以得到不同的服務。
基本介紹
- 中文名:套接字
- 外文名:socket
- 英文原義:“孔”或“插座”地方
- 中文別稱:通常也稱作"套接字"
- 常用類型:流式Socket和數據包式Socket
- 相關模型:對等模型、C/S模型
- 相關套用:C,C++, python, java
- 區號:它的網路地址
舉例說明
現象解釋
連線過程
常用函式
實例
JAVA
package com.socket;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.net.SocketTimeoutException;import java.text.SimpleDateFormat;import java.util.Date;public class SocketServer { public static String _pattern = "yyyy-MM-dd HH:mm:ss SSS"; public static SimpleDateFormat format = new SimpleDateFormat(_pattern); // 設定逾時間 public static int _sec = 0; public static void main(String[] args) { System.out.println("----------Server----------"); System.out.println(format.format(new Date())); ServerSocket server; try { server = new ServerSocket(8001); System.out.println("監聽建立 等你上線\n"); Socket socket = server.accept(); System.out.println(format.format(new Date())); System.out.println("建立了連結\n"); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); socket.setSoTimeout(_sec * 1000); System.out.println(format.format(new Date()) + "\n" + _sec + "秒的時間 快寫\n"); System.out.println(format.format(new Date()) + "\nClient:" + br.readLine() + "\n"); Writer writer = new OutputStreamWriter(socket.getOutputStream()); System.out.println(format.format(new Date())); System.out.println("我在寫回復\n"); writer.write("收到\n"); Thread.sleep(10000); writer.flush(); System.out.println(format.format(new Date())); System.out.println("寫完啦 你收下\n\n\n\n\n"); } catch (SocketTimeoutException e) { System.out.println(format.format(new Date()) + "\n" + _sec + "秒沒給我數據 我下啦\n\n\n\n\n"); e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }}
package com.socket.v3;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.Socket;import java.net.SocketException;import java.net.SocketTimeoutException;import java.text.SimpleDateFormat;import java.util.Date;public class SocketClient { public static String _pattern = "yyyy-MM-dd HH:mm:ss SSS"; public static SimpleDateFormat format = new SimpleDateFormat(_pattern); // 設定逾時間 public static int _sec = 5; public static void main(String[] args) { System.out.println("----------Client----------"); Socket socket = null; try { // 與服務端建立連線 socket = new Socket("127.0.0.1", 8001); socket.setSoTimeout(_sec * 1000); System.out.println(format.format(new Date())); System.out.println("建立了連結\n"); // 往服務寫數據 Writer writer = new OutputStreamWriter(socket.getOutputStream()); System.out.println(format.format(new Date())); System.out.println("我在寫啦\n"); Thread.sleep(10000); writer.write("有沒有收到\n"); System.out.println(format.format(new Date())); System.out.println("寫完啦 你收下\n"); writer.flush(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(format.format(new Date()) + "\n" + _sec + "秒的時間 告訴我你收到了嗎\n"); System.out.println(format.format(new Date()) + "\nServer:" + br.readLine()); } catch (SocketTimeoutException e) { System.out.println(format.format(new Date()) + "\n" + _sec + "秒沒收到回復 我下啦\n\n\n\n\n"); e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }}
C
#include<winsock2.h>#include<stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){ WSADATA wsaData; SOCKET sockServer; SOCKADDR_IN addrServer; SOCKET sockClient; SOCKADDR_IN addrClient; WSAStartup(MAKEWORD(2,2),&wsaData); sockServer=socket(AF_INET,SOCK_STREAM,0); addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IP addrServer.sin_family=AF_INET; addrServer.sin_port=htons(6000);//綁定連線埠6000 bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR)); //Listen監聽端 listen(sockServer,5);//5為等待連線數目 printf("伺服器已啟動:\n監聽中...\n"); int len=sizeof(SOCKADDR); char sendBuf[100];//傳送至客戶端的字元串 char recvBuf[100];//接受客戶端返回的字元串 //會阻塞進程,直到有客戶端連線上來為止 sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len); //接收並列印客戶端數據 recv(sockClient,recvBuf,100,0); printf("%s\n",recvBuf); //關閉socket closesocket(sockClient); WSACleanup();}
#include<winsock2.h>#include<stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){ WSADATA wsaData; SOCKET sockClient;//客戶端Socket SOCKADDR_IN addrServer;//服務端地址 WSAStartup(MAKEWORD(2,2),&wsaData); //新建客戶端socket sockClient=socket(AF_INET,SOCK_STREAM,0); //定義要連線的服務端地址 addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目標IP(127.0.0.1是回送地址) addrServer.sin_family=AF_INET; addrServer.sin_port=htons(6000);//連線連線埠6000 //連線到服務端 connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR)); //傳送數據 char message[20]="HelloSocket!"; send(sockClient,message,strlen(message)+1,0); //關閉socket closesocket(sockClient); WSACleanup();}
PHP
開啟一個socket監聽示例程式:<?php//設定一些基本的變數$host="192.168.1.99";//主機地址$port=1234;//連線埠//設定逾時時間set_time_limit(0);//創建一個Socket$socket=socket_create(AF_INET,SOCK_STREAM,0)ordie("Couldnotcreatesocket\n");//綁定Socket到連線埠$result=socket_bind($socket,$host,$port)ordie("Couldnotbindtosocket\n");//開始監聽連結$result=socket_listen($socket,3)ordie("Couldnotsetupsocketlistener\n");//acceptincomingconnections//另一個Socket來處理通信$spawn=socket_accept($socket)ordie("Couldnotacceptincomingconnection\n");//獲得客戶端的輸入$input=socket_read($spawn,1024)ordie("Couldnotreadinput\n");//清空輸入字元串$input=trim($input);//處理客戶端輸入並返回結果$output=strrev($input)."\n";socket_write($spawn,$output,strlen($output))ordie("Couldnotwriteoutput\n");//關閉socket_close($spawn);socket_close($socket);
C#
public class XmlSocket{ //異步socket偵聽從客戶端傳來的數據 public static string data=null; //Threadsignal.執行緒用一個指示是否將初始狀態設定為終止的布爾值初始化ManualResetEvent類的新實例。 public static ManualResetEvent allDone=new ManualResetEvent(false); static void Main(string[]args) { StartListening(); } public static void StartListening() { //傳入數據緩衝 byte[] bytes = new Byte[1024]; //建立本地連線埠 IPAddress ipAddress; String ipString = ConfigurationManager.AppSettings.Get("SocketIP"); if(ipString == null || ipString == String.Empty) { IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); ipAddress = ipHostInfo.AddressList[0]; } else { ipAddress = IPAddress.Parse(ipString); } int port; String portString = ConfigurationManager.AppSettings.Get("SocketPort"); if(portString == null || portString == String.Empty) { port=11001; } else { port=int.Parse(portString); } IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //綁定連線埠和數據 listener.Bind(localEndPoint); listener.Listen(100); while(true) {//設定無信號狀態的事件 allDone.Reset(); //重啟異步連線 listener.BeginAccept(new AsyncCallback(AcceptCallback),listener); //等待連線創建後繼續 allDone.WaitOne(); } public static void AcceptCallback(IAsyncResult ar) { //接受回調方法。該方法的此節向主應用程式執行緒發出信號,讓它繼續處理並建立與客戶端的連線 allDone.Set(); //獲取客戶端請求句柄 Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback),state); } //與接受回調方法一樣,讀取回調方法也是一個AsyncCallback委託。該方法將來自客戶端套接字的一個或多個位元組讀入數據緩衝區,然後再次調用BeginReceive方法,直到客戶端傳送的數據完成為止。從客戶端讀取整個訊息後,在控制台上顯示字元串,並關閉處理與客戶端的連線的伺服器套接字。 public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; //創建自定義的狀態對象 StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket;//處理的句柄 //讀出 int bytesRead = handler.EndReceive(ar); if(bytesRead>0) { String len = Encoding.UTF8.GetBytes(result).Length.ToString().PadLeft(8,'0'); log.writeLine(len); Send(len + result, handler); } } private static void Send(string data, Socket handler) { byte[] byteData = Encoding.UTF8.GetBytes(data); handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { Socket handler = (Socket)ar.AsyncState; //向遠端傳送數據 int bytesSent = handler.EndSend(ar); StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback),state); handler.Shutdown(SocketShutdown.Both); handler.Close(); } public static void StopListening() { allDone.Close(); log.close(); }}