在現今軟體開發中,網頁程式設計是非常重要的一部分,本文簡單介紹下網路程式設計的概念與實作,需要的朋友可以參考下
閱讀目錄:
基礎
Socket程式設計
多執行緒並發
阻塞式同步IO
基礎
在現今軟體開發中,網路程式設計是非常重要的一部分,本文簡要介紹下網路程式設計的概念和實踐。
Socket是一種網路編程接口,它是對傳輸層TCP、UDP通訊協定的一層封裝,透過友善的API暴露出去,方便在進程或多台機器間進行網路通訊。
Socket程式設計
在網路程式設計中分客戶端和服務端兩個角色,例如透過開啟瀏覽器存取到掛在Web軟體上的網頁,從程式角度來看,即客戶端(瀏覽器)發起了一個Socket請求到伺服器端,伺服器把網頁內容返回到瀏覽器解析後展示。在客戶端和服務端資料通訊前,會進行三次確認才會正式建立連接,也即是三次握手。
客戶端發送訊息詢問服務端是否準備好
服務端回應我準備好了,你呢準備好了嗎
客戶端回應服務端我也準備好了,可以通訊了
##TCP/IP協定是網路間通訊的基礎協議,在不同程式語言及不同作業系統下暴露的Socket介面用法也大同小異,僅是其內部實作有所不同,例如Linux下的epoll和windows下的IOCP。
服務端- 實例化Socket
- #把公用位址連接埠綁定作業系統上
- 開始監聽綁定的連接埠
- 等待客戶端連線
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 6389); Socket listenSocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(ip); listenSocket.Listen(100); listenSocket.Accept();listen
函數中有個int型別參數,它表示最大等待處理連接的數量,表示已建立連接但還未處理的數量,每調用Accept函數一下即從這個等待隊列中拿出一個連接。 通常服務端要服務多個客戶端請求的連接,所以會循環從等待佇列中拿出連接,進行接收發送。
while (true) { var accept= listenSocket.Accept(); accept.Receive(); accept.Send(); }
多執行緒並發上面的服務端程式處理接收和發送訊息都是在目前執行緒下完成的,這意味著要處理完一個客戶端連接後才能去處理下一個連接,如果當前連接是進行資料庫或檔案讀取寫入等IO操作,那會極大浪費伺服器的CPU資源,降低了伺服器吞吐量。
while (true) { var accept = listenSocket.Accept(); ThreadPool.QueueUserWorkItem((obj) => { byte[] receive = new byte[100]; accept.Receive(receive); byte[] send = new byte[100]; accept.Send(receive); }); }如範例中,當監聽到有新連線請求過來時,呼叫Accept()取出目前連線的socket,使用新的執行緒去處理接收和傳送訊息,這樣服務端就能實現fork一個新程序去處理客戶端的連線:
var connfd = Accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); var m = fork(); if(m == 0) { //do something }建立一個新的執行緒處理限流:
var *clientsockfd = accept(serversockfd,(struct sockaddr *)&clientaddress, (socklent *)&clientlen); if(pthreadcreate(&thread, NULL, recdata, clientsockfd)!=0) { //do something }
阻塞式同步IO上述範例中使用的即是該
模型,使用起來簡單方便。
while (true) { var accept = listenSocket.Accept(); byte[] receive = new byte[100]; accept.Receive(receive); byte[] send = new byte[100]; accept.Send(receive); }從呼叫Receive函數起到接受到客戶端發過來的資料期間,該函數會一直阻塞等待著,這個阻塞期間處理流程如下:
- 用戶端傳送資料
- 透過廣域網路區域網路傳送到服務端機器網路卡緩衝區上
- 網路卡驅動對CPU傳送中斷指令
- CPU把資料拷貝到核心緩衝區
- CPU再把核心緩衝區的資料拷貝使用者緩衝區,上面的receive位元組數組。
至此处理成功,开始处理下一个连接请求。 调用发送函数同样会阻塞在当前,然后把用户缓冲区(send字节数组)数据拷贝到内核中TCP发送缓冲区中。 TCP的发送缓冲区也有一定的大小限制,如果发送的数据大于该限制,send函数会一直等待发送缓冲区有空闲时完全拷贝完才会返回,继续处理后续连接请求。
异步IO
上篇提到用多线程处理多个阻塞同步IO而实现并发服务端,这种模式在连接数量比较小的时候非常适合,一旦连接过多,性能会急速下降。 在大多数服务端网络软件中会采用一种异步IO的方式来提高性能。
同步IO方式:连接Receive请求->等待->等待->接收成功
异步IO方式:连接Receive请求->立即返回->事件或回调通知
采用异步IO方式,意味着单线程可以处理多个请求了,连接发起一个Receive请求后,当前线程可以立即去做别的事情,当数据接收完毕通知线程处理即可。
其数据接收分2部分:
数据从别的机器发送内核缓冲区
内核缓冲区拷贝到用户缓冲区
第二部分示例代码:
byte[] msg = new byte[256]; socket.Receive(msg);
介绍这2部分的目的是方便区分其他几种方式。 对于用户程序来说,同步IO和异步IO的区别在于第二部分是否需要等待。
非阻塞式同步IO
非阻塞式同步IO,由同步IO延伸出来,把这个名词拆分成2部分描述:
非阻塞式,指的是上节"数据从别的机器发送内核缓冲区"部分是非阻塞的。
同步IO,指的是上节"内核缓冲区拷贝到用户缓冲区"部分是等待的。
既然是第一部分是非阻塞的,那就需要一种方法得知什么时候内核缓冲区是OK的。 设置非阻塞模式后,在连接调用Receive方法时,会立即返回一个标记,告知用户程序内核缓存区有没有数据,如果有数据开始进行第二部分操作,从内核缓冲区拷贝到用户程序缓冲区。 由于系统会返回个标记,那可以通过轮询方式来判断内核缓冲区是否OK。
设置非阻塞模式参考代码:
SocketInformation sif=new SocketInformation(); sif.Options=SocketInformationOptions.NonBlocking; sif.ProtocolInformation = new byte[24]; Socket socket = new Socket(sif);
轮询参考代码:
while(true) { byte[] msg = new byte[256]; var temp = socket.Receive(msg); if (temp=="OK"){ //do something }else{ continue } }
这种方式近乎淘汰了,了解即可。
基于回调的异步IO
上面介绍过:
异步IO方式:连接Receive请求->立即返回->事件或回调通知
当回调到执行时,数据已经在用户程序缓冲区已经准备好了,在回调代码中对这部分数据进行相应的逻辑即可。
发出接收请求:
static byte[] msg = new byte[256]; var temp = socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(ReadCallback), socket);
回调函数中对数据做处理:
public static void ReadCallback(IAsyncResult ar) { var socket = (Socket)ar.AsyncState; int read = socket.EndReceive(ar); DoSomething(msg); socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(Read_Callback), socket); }
当回调函数执行时,表示数据已经准备好,需要先结束接收请求EndReceive,以便第二次发出接收请求。 在服务端程序中要处理多个客户端的接收,再次发出BeginReceive接收数据请求即可。
这里的回调函数是在另外一个线程的触发,必要时要对数据加锁防止数据竞争:
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
以上是C#網路程式設計的圖文代碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

C#和.NET提供了強大的功能和高效的開發環境。 1)C#是一種現代、面向對象的編程語言,結合了C 的強大和Java的簡潔性。 2).NET框架是一個用於構建和運行應用程序的平台,支持多種編程語言。 3)C#中的類和對像是面向對象編程的核心,類定義數據和行為,對像是類的實例。 4).NET的垃圾回收機制自動管理內存,簡化開發者的工作。 5)C#和.NET提供了強大的文件操作功能,支持同步和異步編程。 6)常見錯誤可以通過調試器、日誌記錄和異常處理來解決。 7)性能優化和最佳實踐包括使用StringBuild

.NETFramework是一個跨語言、跨平台的開發平台,提供一致的編程模型和強大的運行時環境。 1)它由CLR和FCL組成,CLR管理內存和線程,FCL提供預構建功能。 2)使用示例包括讀取文件和LINQ查詢。 3)常見錯誤涉及未處理異常和內存洩漏,需使用調試工具解決。 4)性能優化可通過異步編程和緩存實現,保持代碼可讀性和可維護性是關鍵。

C#.NET保持持久吸引力的原因包括其出色的性能、豐富的生態系統、強大的社區支持和跨平台開發能力。 1)性能表現優異,適用於企業級應用和遊戲開發;2).NET框架提供了廣泛的類庫和工具,支持多種開發領域;3)擁有活躍的開發者社區和豐富的學習資源;4).NETCore實現了跨平台開發,擴展了應用場景。

C#.NET中的設計模式包括Singleton模式和依賴注入。 1.Singleton模式確保類只有一個實例,適用於需要全局訪問點的場景,但需注意線程安全和濫用問題。 2.依賴注入通過注入依賴提高代碼靈活性和可測試性,常用於構造函數注入,但需避免過度使用導致複雜度增加。

C#.NET在現代世界中廣泛應用於遊戲開發、金融服務、物聯網和雲計算等領域。 1)在遊戲開發中,通過Unity引擎使用C#進行編程。 2)金融服務領域,C#.NET用於開發高性能的交易系統和數據分析工具。 3)物聯網和雲計算方面,C#.NET通過Azure服務提供支持,開發設備控制邏輯和數據處理。

C#.NET開發者社區提供了豐富的資源和支持,包括:1.微軟的官方文檔,2.社區論壇如StackOverflow和Reddit,3.GitHub上的開源項目,這些資源幫助開發者從基礎學習到高級應用,提升編程技能。

C#.NET的優勢包括:1)語言特性,如異步編程簡化了開發;2)性能與可靠性,通過JIT編譯和垃圾回收機制提升效率;3)跨平台支持,.NETCore擴展了應用場景;4)實際應用廣泛,從Web到桌面和遊戲開發都有出色表現。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SublimeText3漢化版
中文版,非常好用

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!