C#上位機之網口通信與協議!

文章目錄

  • 前言
  • 一、網口通信概念
  • 二、使用網口通信準備
  • 三、使用步驟


前言

C#上位機之網口通信與協議!


一、網口通信概念

定義 :Socket 可以理解為一個通信端點,它提供了應用程序與網絡之間的接口,使得應用程序能夠在網絡上發送和接收數據。通過 Socket,不同設備上的應用程序可以建立連接,實現數據的交換。
地址族 :用于確定 Socket 能夠使用的協議類型,常見的有 AF_INET(IPv4 地址族)、AF_INET6(IPv6 地址族)、AF_UNIX(本地通信的 UNIX 域協議)等。
類型
流式套接字(SOCK_STREAM) :提供面向連接的、可靠的、雙向的字節流服務,基于 TCP 協議。數據傳輸保證順序、完整且無重復,適用于對數據可靠性要求較高的場景,如文件傳輸、遠程登錄等。
數據報套接字(SOCK_DGRAM) :提供無連接的、不可靠的、基于數據報的包傳輸服務,基于 UDP 協議。數據報獨立傳輸,可能存在丟失、重復或亂序的情況,但傳輸效率較高,適用于對實時性要求較高、少量丟包可以接受的場景,如視頻直播、在線游戲等。
原始套接字(SOCK_RAW) :允許對低層協議進行訪問和操作,可直接處理 IP 數據報或更低層協議的數據,通常用于網絡工具開發、協議研究等特殊場景。

二、使用網口通信準備

1、下載網絡調試助手軟件
在這里插入圖片描述
2、Socket概念
地址族(AddressFamily):如 InterNetwork (IPv4)、InterNetworkV6 (IPv6)。
套接字類型(SocketType):如 Stream (TCP)、Dgram (UDP)。
協議類型(ProtocolType):如 Tcp 、Udp 。
IPEndPoint:表示網絡終結點(IP 地址 + 端口)。
3、Socket工作流程

階段服務器端操作客戶端操作
創建套接字(Socket)創建一個 Socket 對象,指定地址族、套接字類型和協議類型。創建一個 Socket 對象,指定地址族、套接字類型和協議類型。
綁定地址(Bind)使用 Bind 方法將套接字綁定到本地的 IP 地址和端口號。通常不需要顯式綁定,除非需要指定本地地址和端口。
監聽連接(Listen)調用 Listen 方法開始監聽來自客戶端的連接請求,進入監聽狀態,等待客戶端連接。(僅TCP)無此操作。
建立連接(Accept)調用 Accept 方法接受客戶端的連接請求,建立與客戶端之間的連接,返回一個新的套接字用于與客戶端通信(僅TCP)。調用 Connect 方法向服務器端發起連接請求,嘗試與服務器端建立連接。
數據傳輸通過返回的套接字使用 Receive 方法接收客戶端發送的數據,使用 Send 方法向客戶端發送數據。通過套接字使用 Send 方法向服務器端發送數據,使用 Receive 方法接收服務器端發送的數據。
關閉連接(Close)數據傳輸完成后,調用 Shutdown 方法關閉套接字的發送和接收功能,然后調用 Close 方法釋放套接字資源,關閉連接。數據傳輸完成后,調用 Shutdown 方法關閉套接字的發送和接收功能,然后調用 Close 方法釋放套接字資源,關閉連接。

三、使用步驟

TCP服務器
C#創建socket服務端,但這種方法只能接收一個客戶端連接和處理一次接收到的信息。解釋:當啟動服務端后程序會停在Socket socketClient = socketServer.Accept();處等待客戶端連接,當有客戶端來連接程序就會停在int bytesReader = socketClient.Receive(recvData);等待客戶端發送消息。

// 1、創建Socket
Socket socketServer = new Socket(AddressFamily.InterNetwork,// 地址族IPv4SocketType.Stream, // 套接字類型ProtocolType.Tcp// TCP協議);
// 2、綁定IP和端口
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
socketServer.Bind(endPoint);// 3、開始監聽
socketServer.Listen();
Debug.WriteLine($"服務器已啟動,等待連接");// 4、接收客戶端連接
Socket socketClient = socketServer.Accept();
Debug.WriteLine($"連接的客戶端:{socketClient.RemoteEndPoint}");// 5、接收數據
byte[] recvData = new byte[1024];
int bytesReader = socketClient.Receive(recvData);// 返回接收到的字節數
Debug.WriteLine($"收到的消息:{Encoding.UTF8.GetString(recvData,0, bytesReader)}");// 6、發送響應
byte[] sendMes = Encoding.UTF8.GetBytes("Hello I am Server");
socketClient.Send(sendMes);// 7、關閉連接
//socketClient.Close();
//socketServer.Close();

如果需要連接多個客戶端和接收信息,可以使用While循環來實現

// 1、創建Socket
Socket socketServer = new Socket(AddressFamily.InterNetwork,// 地址族IPv4SocketType.Stream, // 套接字類型ProtocolType.Tcp// TCP協議);
// 2、綁定IP和端口
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
socketServer.Bind(endPoint);// 3、開始監聽
socketServer.Listen();
Debug.WriteLine($"服務器已啟動,等待連接");
while (true)
{// 4、接收客戶端連接Socket socketClient = socketServer.Accept();Debug.WriteLine($"連接的客戶端:{socketClient.RemoteEndPoint}");while (true){// 5、接收數據byte[] recvData = new byte[1024];int bytesReader = socketClient.Receive(recvData);// 返回接收到的字節數Debug.WriteLine($"收到的消息:{Encoding.UTF8.GetString(recvData, 0, bytesReader)}");// 6、發送響應byte[] sendMes = Encoding.UTF8.GetBytes("Hello I am Server");socketClient.Send(sendMes);}
}

但是使用上述方法程序在

while (true)
{// 5、接收數據byte[] recvData = new byte[1024];int bytesReader = socketClient.Receive(recvData);// 返回接收到的字節數Debug.WriteLine($"收到的消息:{Encoding.UTF8.GetString(recvData, 0, bytesReader)}");// 6、發送響應byte[] sendMes = Encoding.UTF8.GetBytes("Hello I am Server");socketClient.Send(sendMes);
}

這段代碼處陷入死循環,只能重復接收一個客戶端的消息。
如何解決上述的問題呢?
可以使用Task線程來解決。相當于每來一個客戶端就創建一個線程來處理這個客戶端發送的數據。

// 1、創建Socket
Socket socketServer = new Socket(AddressFamily.InterNetwork,// 地址族IPv4SocketType.Stream, // 套接字類型ProtocolType.Tcp// TCP協議);
// 2、綁定IP和端口
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
socketServer.Bind(endPoint);// 3、開始監聽
socketServer.Listen();
Debug.WriteLine($"服務器已啟動,等待連接");
while (true)
{// 4、接收客戶端連接Socket socketClient = socketServer.Accept();Debug.WriteLine($"連接的客戶端:{socketClient.RemoteEndPoint}");Task.Factory.StartNew(() =>{while (true){// 5、接收數據byte[] recvData = new byte[1024];int bytesReader = socketClient.Receive(recvData);// 返回接收到的字節數Debug.WriteLine($"收到的消息:{Encoding.UTF8.GetString(recvData, 0, bytesReader)}");// 6、發送響應byte[] sendMes = Encoding.UTF8.GetBytes("Hello I am Server");socketClient.Send(sendMes);}});
}
// 7、關閉連接
//socketClient.Close();
//socketServer.Close();

部分代碼解讀:

Task.Factory.StartNew 創建一個線程并開啟這個線程。

TCP客戶端

//  1、創建Socket
Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 2、連接服務器
IPEndPoint serverPoin = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
socketClient.Connect(serverPoin);
Debug.WriteLine($"已連接到服務器");// 3、發送數據
byte[] senfMsg = Encoding.UTF8.GetBytes("I am Client");
socketClient.Send(senfMsg);// 4、接收響應
byte[] recvMsg = new byte[1024];
int bytesReader = socketClient.Receive(recvMsg);
string response = Encoding.UTF8.GetString(recvMsg, 0,bytesReader);
Debug.WriteLine($"接收到的消息:{response}");// 5、關閉連接
//socketClient.Close();

UDP通信

// 1、創建UDP
Socket udp = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
// 2.綁定端口
udp.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));// 1、指定地址
EndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
// 2、給指定地址發送信息
udp.SendTo(Encoding.UTF8.GetBytes("Hello UDP"),endPoint);// 接收信息的字節數組
byte[] buffer = new byte[1024];
// IPAddress.Any 服務器會接受來自任何網絡接口的連接請求,表示端口號由操作系統自動分配
endPoint = new IPEndPoint(IPAddress.Any, 0);
// 參數ref endPoint指定接收數據的來源
int bytesReader = udp.ReceiveFrom(buffer,ref endPoint);
string message = Encoding.UTF8.GetString(buffer, 0, bytesReader);
Debug.WriteLine(message);// 2、廣播模式
udp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
endPoint = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 9999);
udp.SendTo(Encoding.UTF8.GetBytes("Hello UDP!-BroadCast"), endPoint);

TcpClient,簡化了 TCP 協議的通信流程。

構造方法說明
TcpClient()初始化一個新的 TcpClient 實例,不指定遠程主機和端口。
TcpClient(string hostname, int port)初始化一個新的 TcpClient 實例,并連接到指定的遠程主機和端口。
屬性說明使用方法示例
Client獲取底層的 Socket 對象,用于更細粒度的網絡操作。Socket socket = tcpClient.Client;
Connected獲取一個布爾值,指示 TcpClient 是否連接到遠程主機。if (tcpClient.Connected) { ... }
Available獲取接收緩沖區中等待接收的字節數。int availableBytes = tcpClient.Available;
ReceiveBufferSize獲取或設置接收緩沖區的大小。int bufferSize = tcpClient.ReceiveBufferSize;tcpClient.ReceiveBufferSize = 1024;
SendBufferSize獲取或設置發送緩沖區的大小。int bufferSize = tcpClient.SendBufferSize;tcpClient.SendBufferSize = 1024;
方法說明使用方法示例
Connect(string host, int port)連接到遠程 TCP 服務器的指定主機和端口。tcpClient.Connect("127.0.0.1", 8888);
GetStream()返回一個 NetworkStream 對象,用于在 TcpClient 上進行讀寫操作。NetworkStream stream = tcpClient.GetStream();
Close()關閉 TcpClient 和其底層的 SockettcpClient.Close();
Dispose()釋放 TcpClient 使用的資源。tcpClient.Dispose();

TCP客戶端

// 1、創建TcpClient
using ( TcpClient client = new TcpClient())
{client.Connect("127.0.0.1",8888);Debug.WriteLine("已連接到服務器");// 2、獲取網絡流NetworkStream stream = client.GetStream();// 3、發送數據string message = "Hello Server!";byte[] sentBytes = Encoding.UTF8.GetBytes(message);stream.Write(sentBytes, 0, sentBytes.Length);Debug.WriteLine($"發送:{message}");// 4、接收響應byte[] buffer = new byte[1024];int bytesRead = stream.Read(buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer);Debug.WriteLine(response);

TCP服務端

// 監聽指定IP和端口
TcpListener server = new TcpListener(IPAddress.Any, 8888);
server.Start();
Debug.WriteLine($"服務器已啟動,等待連接.....");try
{// 接收客戶端連接using (TcpClient client = server.AcceptTcpClient()){Debug.WriteLine($"客戶端已連接:{((IPEndPoint)client.Client.RemoteEndPoint).Address}");// 2、獲取網絡流NetworkStream stream = client.GetStream();// 3、接收數據byte[] buffer = new byte[1024];int bytesRead = stream.Read(buffer, 0, buffer.Length);string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);Debug.WriteLine(message);// 4、發送響應string response = "Hello Client!";byte[] sendData = Encoding.UTF8.GetBytes(response);stream.Write(sendData, 0, sendData.Length);}
}catch(Exception ex)
{Debug.WriteLine($"錯誤:{ex.Message}");
}
finally
{server.Stop();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87721.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87721.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87721.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android Studio 創建類時如何自動添加類注釋

打開IDEA或AS,點擊菜單欄File——Settings——Editor——File and Code Templates。 點擊右邊Tab頁的Includes,選擇File Header,修改類頭模版,如圖: 記得選中Project,否則默認是整個AS都會進行設置

C++11:shared_ptr的設計哲學(原理+源碼):內存安全和性能的架構權衡

0.簡介 在C編程世界中,內存管理是一把雙刃劍,手動管理帶來了極致的內存控制能力,但也帶來了像內存泄漏,野指針等問題;自動垃圾回收雖然安全,但卻會帶來一定的性能損耗。本文將介紹C11引入shared_ptr&#…

Mysql EXPLAIN 執行計劃

EXPLAIN SELECT SQl。。。。界面filtered儲引擎返回的數據在經過服務器層 WHERE 條件過濾后,剩余數據占總行數的百分比估計值rows * filtered/100 越接近100%效率越高rowspossible_keys 可能選擇的索引key最終決定選擇的行partitions問了哪些分區select_type查詢…

力扣刷題記錄【1】146.LRU緩存

前言: 請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類: LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存中,則返回關鍵字的值&…

西門子S7-1200 PLC主流通信方法及應用

一、通信基礎 1. 網絡術語與設備 - 關鍵設備:交換機、路由器、網關等。 - 物理接口:RS-485(支持多點通信)、RS-232C(點對點串行通信)。 2. OSI參考模型 - 核心框架:理解協議分層&…

MySQL實現任意級子目錄的主要方案以及區別

常見的實現方案及區別 1. 鄰接表(Adjacency List) 方案描述: 每條記錄存儲一個節點的父節點ID。 表結構大致: id INT PRIMARY KEY, name VARCHAR(...), parent_id INT -- 指向父節點的ID,根節點為NULL或0優點&…

Linux網絡socket套接字(完)(5)

文章目錄前言一、多進程版的Tcp網絡程序捕捉SIGCHLD信號讓孫子進程提供服務二、多線程版的Tcp網絡程序三、線程池版的Tcp網絡程序四、Tcp協議通訊流程通訊流程總覽三次握手的過程數據傳輸的過程四次揮手的過程總結前言 結束嘍,至少這個Tcp套接字有關內容要結束了~ ?…

Web3 Study Log 003

Web3 Study Log 003 2025-7-5 這幾天各種各樣的瑣事,處理完了,真的煩,估計能消停一段時間了… 今天終于能夠坐下來好好學習,今天學習了chainlink的使用,能夠獲取 ETH/USD 實時價格,然后寫了一個簡單的眾…

Kotlin:2.1.20 的新特性

一、概述 The Kotlin 2.1.20 release is here! Here are the main highlights: Kotlin 2.1.20發布了,主要亮點如下: K2 compiler updates: updates to the new kapt and Lombok pluginsKotlin Multiplatform: new DSL to replace Gradle’s Application …

設計模式 | 觀察者模式

觀察者模式(Observer Pattern)是行為型設計模式中的事件通知專家,它定義了對象間一種一對多的依賴關系,當一個對象狀態改變時,所有依賴它的對象都會自動收到通知并更新。這種模式實現了發布-訂閱機制,是事件…

Apache Struts2 遠程命令執行漏洞(S2-052)

一、漏洞概述 S2-052 是 Apache Struts2 框架中一個高危的遠程代碼執行漏洞(CVE-2017-9805),由安全研究人員于 2017 年發現并公開。該漏洞源于 Struts2 的 REST 插件在使用 XStream 組件處理 XML 反序列化時,未對用戶輸入的 XML 數…

RS觸發器Multisim電路仿真——硬件工程師筆記

目錄 1 RS觸發器基礎知識 1.1 工作原理 1.2 電路結構 1.3 特點 1.4 應用 1.5 設計考慮 1.6 總結 2 與非門實現基本RS觸發器 2.1 電路結構 2.2 工作原理 2.3 特點 2.4 總結 3 或非門實現基本RS觸發器 3.1 電路結構 3.2 工作原理 3.3 特點 3.4 總結 4 與非門實…

提示技術系列(12)——程序輔助語言模型

什么是提示技術? 提示技術是實現提示工程目標的具體技術手段,是提示工程中的“工具庫”。 什么又是提示工程? 提示工程是指通過設計、優化和迭代輸入到大語言模型(LLM)的提示(Prompt)&#xff…

明遠智睿H618:開啟多場景智慧生活新時代

在數字化浪潮的推動下,智能設備正深刻地改變著我們的生活方式。明遠智睿H618以其強大的功能和卓越的性能,在家庭娛樂、商業展示、教育培訓和智能家居控制等多個領域展現出巨大的應用潛力,開啟了多場景智慧生活的新時代。 家庭娛樂&#xff1…

探秘展銷編輯器:相較于傳統展銷的卓越優勢與甄選指南?

在競爭激烈的商業環境中,企業期望通過展銷活動提升品牌知名度、推廣產品和拓展市場,但傳統展銷方式存在諸多難題。一是場地限制,優質場地稀缺、租金貴、檔期緊,場地空間和布局也不一定合適;二是展示形式單一,多為靜態展…

第31篇:塊設備與字符設備管理深度解析(基于OpenEuler 24.03)

塊設備與字符設備管理深度解析(基于OpenEuler 24.03) 文章目錄 塊設備與字符設備管理深度解析(基于OpenEuler 24.03)一、設備基礎概念體系1.1 塊設備的核心特性與分類1.2 字符設備的流式數據模型1.3 設備標識系統:主設…

Django Channels WebSocket實時通信實戰:從聊天功能到消息推送

引言 在Web開發中,實時通信功能(如在線聊天、實時通知、數據推送)已成為許多應用的核心需求。傳統的HTTP協議由于其請求-響應模式的限制,無法高效實現實時通信。WebSocket作為一種全雙工通信協議,為實時Web應用提供了…

day52 神經網絡調參指南

目錄 隨機種子 內參的初始化 神經網絡調參指南 參數的分類 調參順序 初始化參數 batchsize的選擇 學習率調整 激活函數的選擇 損失函數的選擇 模型架構中的參數 正則化系數 其他補充 隨機種子 import torch import torch.nn as nn# 定義簡單的線性模型&#xf…

.NET9 實現斐波那契數列(FibonacciSequence)性能測試

在 .NET 平臺上實現 斐波那契數列 并使用 BenchmarkDotNet 進行性能測試&#xff0c;是評估不同算法實現方式性能表現的一種高效且標準化的方法。通過該方式&#xff0c;可以對比遞歸、迭代、記憶化遞歸以及結合高性能優化技術&#xff08;如 Span<T>、Memory<T> 和…

三、docker軟件安裝:gitlab,nexus,mysql8,redis,nacos,nginx

目錄 1.gitlab安裝 2.nexus安裝 (1)下載啟動 (2)設置中央倉庫遠程地址 (3)配置maven的settings.xml 3.mysql8安裝 4.redis安裝 5.nacos安裝 6.nginx安裝 1.gitlab安裝 #創建目錄 cd /usr/local/ mkdir docker cd docker/ mkdir gitlab_docker cd gitlab_docker…