UNIX Socket(也稱為本地套接字或IPC套接字)是一種在同一臺計算機上進行進程間通信(IPC)的機制。它提供了一種可靠而高效的方式,使不同進程之間能夠直接交換數據。UNIX Socket基于文件系統的抽象概念,使用一個特殊的文件來表示套接字。與網絡套接字不同,UNIX Socket僅限于同一主機上的進程間通信,不涉及網絡協議棧的使用。
UNIX Socket允許進程進行同步或異步通信。對于同步通信,發送進程會阻塞直到接收進程接收到數據;對于異步通信,發送進程可以繼續執行其他任務而不需要等待接收進程響應。
UNIX Socket允許進程在同一個套接字上進行雙向通信,既可以發送數據也可以接收數據。
UNIX Socket以字節流的形式傳輸數據,不關心數據的消息邊界。這意味著發送的數據可以分割成多個部分,也可以將多個消息組合成一個單獨的數據塊。
由于UNIX Socket只涉及本地通信,沒有網絡協議的開銷,因此它通常比網絡套接字更高效。
由于UNIX Socket 使用套接字的概念,類似于網絡套接字,但其使用的是文件系統路徑而不是IP地址和端口號。 UNIX Socket 具有以下優點:
UNIX Socket可以在不同編程語言中使用,并且廣泛應用于各種場景,例如:
創建 Socket:
綁定 Socket 到地址:
監聽連接請求(對于面向連接型套接字):
接受連接請求(對于面向連接型套接字):
進行數據傳輸:
關閉 Socket:
在WPF應用程序中創建UNIX Socket的服務端和客戶端,可以使用System.Net.Sockets.Socket類。
服務端(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); } // 綁定并開始監聽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"); // 要發送的數據 clientSocket.Send(buffer); // 向客戶端發送數據 clientSocket.Close(); // 關閉客戶端連接 } }); } 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)); // 連接到服務端 byte[] buffer = new byte[1024]; int bytesRead = socket.Receive(buffer); // 接收數據 string receivedData = Encoding.ASCII.GetString(buffer, 0, bytesRead); ReceiveTextBox.Text = receivedData; // 顯示接收到的數據 socket.Close(); // 關閉客戶端連接 } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}", "Connection Error", MessageBoxButton.OK, MessageBoxImage.Error); } } }}
在這個例子中,主窗口分別包含一個“Start”按鈕(服務端)和一個“Connect”按鈕(客戶端),以及一個用于展示接收到的數據的文本框。服務端代碼負責創建UNIX Socket并綁定到指定的文件路徑,然后開始監聽連接請求。當客戶端連接時,服務端向客戶端發送一條消息,并關閉連接。客戶端代碼負責連接到服務端的UNIX Socket,接收服務端發送的數據,并將接收到的數據顯示在文本框中。
使用UNIX Socket進行進程間通信時,序列化是一個重要的問題。由于UNIX Socket只能傳輸字節流,而對象是無法直接傳輸的,因此需要將對象進行序列化成字節流再傳輸,接收方接收到字節流后再進行反序列化還原為對象。常用的解決方案有:
案例演示如何使用BinaryFormatter進行對象的二進制序列化和反序列化:
using System;using System.IO;using System.Net.Sockets;using System.Runtime.Serialization.Formatters.Binary;// 發送方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 }; // 要傳輸的對象var formatter = new BinaryFormatter();using (var stream = new MemoryStream()){ formatter.Serialize(stream, data); // 對象序列化到內存流中 var buffer = stream.ToArray(); // 獲取字節流數據 socket.Send(buffer); // 發送字節流}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); // 接收字節流using (var stream = new MemoryStream(receivedBuffer, 0, bytesRead)){ var receivedData = formatter.Deserialize(stream) as MyData; // 字節流反序列化為對象 Console.WriteLine($"Received: {receivedData.Name}, {receivedData.Age}");}clientSocket.Close();listener.Close();// 要傳輸的數據結構[Serializable]public class MyData{ public string Name { get; set; } public int Age { get; set; }}
在這個示例中,發送方將MyData對象進行二進制序列化,并通過UNIX Socket發送字節流。接收方接收到字節流后,使用相同的二進制序列化方式進行反序列化還原為MyData對象。要注意的是,由于不同平臺和不同開發環境的序列化機制可能存在差異,因此在進行跨平臺的進程間通信時,需要確保序列化方式的兼容性。另外,如果要序列化的對象是自定義類或結構體,需要將其標記為可序列化(使用[Serializable]特性)才能進行序列化和反序列化操作。
本文鏈接:http://www.www897cc.com/showinfo-26-57914-0.htmlUNIX Socket:不同進程之間能夠直接交換數據進行進程間通信(IPC)
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com