UNIX Socket(也稱為本地套接字或IPC套接字)是一種在同一臺計算機上進行進程間通信(IPC)的機制。它提供了一種可靠而高效的方式,使不同進程之間能夠直接交換數(shù)據(jù)。UNIX Socket基于文件系統(tǒng)的抽象概念,使用一個特殊的文件來表示套接字。與網(wǎng)絡(luò)套接字不同,UNIX Socket僅限于同一主機上的進程間通信,不涉及網(wǎng)絡(luò)協(xié)議棧的使用。
UNIX Socket允許進程進行同步或異步通信。對于同步通信,發(fā)送進程會阻塞直到接收進程接收到數(shù)據(jù);對于異步通信,發(fā)送進程可以繼續(xù)執(zhí)行其他任務(wù)而不需要等待接收進程響應(yīng)。
UNIX Socket允許進程在同一個套接字上進行雙向通信,既可以發(fā)送數(shù)據(jù)也可以接收數(shù)據(jù)。
UNIX Socket以字節(jié)流的形式傳輸數(shù)據(jù),不關(guān)心數(shù)據(jù)的消息邊界。這意味著發(fā)送的數(shù)據(jù)可以分割成多個部分,也可以將多個消息組合成一個單獨的數(shù)據(jù)塊。
由于UNIX Socket只涉及本地通信,沒有網(wǎng)絡(luò)協(xié)議的開銷,因此它通常比網(wǎng)絡(luò)套接字更高效。
由于UNIX Socket 使用套接字的概念,類似于網(wǎng)絡(luò)套接字,但其使用的是文件系統(tǒng)路徑而不是IP地址和端口號。 UNIX Socket 具有以下優(yōu)點:
UNIX Socket可以在不同編程語言中使用,并且廣泛應(yīng)用于各種場景,例如:
創(chuàng)建 Socket:
綁定 Socket 到地址:
監(jiān)聽連接請求(對于面向連接型套接字):
接受連接請求(對于面向連接型套接字):
進行數(shù)據(jù)傳輸:
關(guān)閉 Socket:
在WPF應(yīng)用程序中創(chuàng)建UNIX Socket的服務(wù)端和客戶端,可以使用System.Net.Sockets.Socket類。
服務(wù)端(Server):
using System;using System.Net.Sockets;using System.Text;using System.Threading.Tasks;using System.Windows;namespace UnixSocketExample{ public partial class MainWindow : Window { private const string SocketFilePath = "/path/to/unix/socket"; // UNIX Socket文件路徑 public MainWindow() { InitializeComponent(); } private async void StartButton_Click(object sender, RoutedEventArgs e) { try { var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); // 如果Socket文件已存在,則先刪除 if (System.IO.File.Exists(SocketFilePath)) { System.IO.File.Delete(SocketFilePath); } // 綁定并開始監(jiān)聽UNIX Socket socket.Bind(new UnixDomainSocketEndPoint(SocketFilePath)); socket.Listen(1); await Task.Run(() => { while (true) { var clientSocket = socket.Accept(); // 接受客戶端連接 byte[] buffer = Encoding.ASCII.GetBytes("Hello from server"); // 要發(fā)送的數(shù)據(jù) clientSocket.Send(buffer); // 向客戶端發(fā)送數(shù)據(jù) clientSocket.Close(); // 關(guān)閉客戶端連接 } }); } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}", "Server Error", MessageBoxButton.OK, MessageBoxImage.Error); } } }}
客戶端(Client):
using System;using System.Net.Sockets;using System.Text;using System.Windows;namespace UnixSocketExample{ public partial class MainWindow : Window { private const string SocketFilePath = "/path/to/unix/socket"; // UNIX Socket文件路徑 public MainWindow() { InitializeComponent(); } private void ConnectButton_Click(object sender, RoutedEventArgs e) { try { var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); socket.Connect(new UnixDomainSocketEndPoint(SocketFilePath)); // 連接到服務(wù)端 byte[] buffer = new byte[1024]; int bytesRead = socket.Receive(buffer); // 接收數(shù)據(jù) string receivedData = Encoding.ASCII.GetString(buffer, 0, bytesRead); ReceiveTextBox.Text = receivedData; // 顯示接收到的數(shù)據(jù) socket.Close(); // 關(guān)閉客戶端連接 } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}", "Connection Error", MessageBoxButton.OK, MessageBoxImage.Error); } } }}
在這個例子中,主窗口分別包含一個“Start”按鈕(服務(wù)端)和一個“Connect”按鈕(客戶端),以及一個用于展示接收到的數(shù)據(jù)的文本框。服務(wù)端代碼負(fù)責(zé)創(chuàng)建UNIX Socket并綁定到指定的文件路徑,然后開始監(jiān)聽連接請求。當(dāng)客戶端連接時,服務(wù)端向客戶端發(fā)送一條消息,并關(guān)閉連接。客戶端代碼負(fù)責(zé)連接到服務(wù)端的UNIX Socket,接收服務(wù)端發(fā)送的數(shù)據(jù),并將接收到的數(shù)據(jù)顯示在文本框中。
使用UNIX Socket進行進程間通信時,序列化是一個重要的問題。由于UNIX Socket只能傳輸字節(jié)流,而對象是無法直接傳輸?shù)模虼诵枰獙ο筮M行序列化成字節(jié)流再傳輸,接收方接收到字節(jié)流后再進行反序列化還原為對象。常用的解決方案有:
案例演示如何使用BinaryFormatter進行對象的二進制序列化和反序列化:
using System;using System.IO;using System.Net.Sockets;using System.Runtime.Serialization.Formatters.Binary;// 發(fā)送方var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);socket.Connect(new UnixDomainSocketEndPoint("/path/to/unix/socket"));var data = new MyData { Name = "Alice", Age = 30 }; // 要傳輸?shù)膶ο髒ar formatter = new BinaryFormatter();using (var stream = new MemoryStream()){ formatter.Serialize(stream, data); // 對象序列化到內(nèi)存流中 var buffer = stream.ToArray(); // 獲取字節(jié)流數(shù)據(jù) socket.Send(buffer); // 發(fā)送字節(jié)流}socket.Close();// 接收方var listener = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);listener.Bind(new UnixDomainSocketEndPoint("/path/to/unix/socket"));listener.Listen(1);var clientSocket = listener.Accept();var receivedBuffer = new byte[1024];var bytesRead = clientSocket.Receive(receivedBuffer); // 接收字節(jié)流using (var stream = new MemoryStream(receivedBuffer, 0, bytesRead)){ var receivedData = formatter.Deserialize(stream) as MyData; // 字節(jié)流反序列化為對象 Console.WriteLine($"Received: {receivedData.Name}, {receivedData.Age}");}clientSocket.Close();listener.Close();// 要傳輸?shù)臄?shù)據(jù)結(jié)構(gòu)[Serializable]public class MyData{ public string Name { get; set; } public int Age { get; set; }}
在這個示例中,發(fā)送方將MyData對象進行二進制序列化,并通過UNIX Socket發(fā)送字節(jié)流。接收方接收到字節(jié)流后,使用相同的二進制序列化方式進行反序列化還原為MyData對象。要注意的是,由于不同平臺和不同開發(fā)環(huán)境的序列化機制可能存在差異,因此在進行跨平臺的進程間通信時,需要確保序列化方式的兼容性。另外,如果要序列化的對象是自定義類或結(jié)構(gòu)體,需要將其標(biāo)記為可序列化(使用[Serializable]特性)才能進行序列化和反序列化操作。
本文鏈接:http://www.www897cc.com/showinfo-26-57914-0.htmlUNIX Socket:不同進程之間能夠直接交換數(shù)據(jù)進行進程間通信(IPC)
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com