小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

c#Socket通信實(shí)例

 小樣樣樣樣樣樣 2021-03-17

        在上一篇文章中介紹了Socket基礎(chǔ)—TCP與UDP協(xié)議和他們之間的區(qū)別,這篇文章參考另一位前輩的博文重點(diǎn)記錄下Socket的原理及兩種協(xié)議的開(kāi)發(fā)過(guò)程。

一、Socket通信簡(jiǎn)介

 1.按慣例先來(lái)介紹下socket

        Windows中的很多東西都是從Unix領(lǐng)域借鑒過(guò)來(lái)的,Socket也是一樣。在Unix中,socket代表了一種文件描述符(在Unix中一切都是以文件為單位),而這里這個(gè)描述符則是用于描述網(wǎng)絡(luò)訪(fǎng)問(wèn)的。什么意思呢?就是程序員可以通過(guò)socket來(lái)發(fā)送和接收網(wǎng)絡(luò)上的數(shù)據(jù)。你也可以理解成是一個(gè)API。有了它,你就不用直接去操作網(wǎng)卡了,而是通過(guò)這個(gè)接口,這樣就省了很多復(fù)雜的操作。
在C#中,MS為我們提供了 System.Net.Sockets 命名空間,里面包含了Socket類(lèi)。

2.有了socket,那就可以用它來(lái)訪(fǎng)問(wèn)網(wǎng)絡(luò)了

      不過(guò)你不要高興得太早,要想訪(fǎng)問(wèn)網(wǎng)絡(luò),還得有些基本的條件(和編程無(wú)關(guān)的我就不提了):a. 要確定本機(jī)的IP和端口,socket只有與某一IP和端口綁定,才能發(fā)揮強(qiáng)大的威力。b. 得有協(xié)議吧(否則誰(shuí)認(rèn)得你這發(fā)送到網(wǎng)絡(luò)的是什么呀)。想要復(fù)雜的,我們可以自己來(lái)定協(xié)議。但是這個(gè)就不在這篇里提了,我這里介紹兩種大家最熟悉不過(guò)的協(xié)議:TCP & UDP。(別說(shuō)你不知道,不然...不然...我不告訴你)
如果具備了基本的條件,就可以開(kāi)始用它們?cè)L問(wèn)網(wǎng)絡(luò)了。來(lái)看看步驟吧:
a. 建立一個(gè)套接字
b. 綁定本機(jī)的IP和端口
c. 如果是TCP,因?yàn)槭敲嫦蜻B接的,所以要利用Listen()方法來(lái)監(jiān)聽(tīng)網(wǎng)絡(luò)上是否有人給自己發(fā)東西;如果是UDP,因?yàn)槭菬o(wú)連接的,所以來(lái)者不拒。
d. TCP情況下,如果監(jiān)聽(tīng)到一個(gè)連接,就可以使用accept來(lái)接收這個(gè)連接,然后就可以利用Send/Receive來(lái)執(zhí)行操作了。而UDP,則不需要accept, 直接使用SendTo/ReceiveFrom來(lái)執(zhí)行操作。(看清楚哦,和TCP的執(zhí)行方法有區(qū)別,因?yàn)閁DP不需要建立連接,所以在發(fā)送前并不知道對(duì)方的IP和端口,因此需要指定一個(gè)發(fā)送的節(jié)點(diǎn)才能進(jìn)行正常的發(fā)送和接收)
e. 如果你不想繼續(xù)發(fā)送和接收了,就不要浪費(fèi)資源了。能close的就close吧。

   面向連接的套接字系統(tǒng)調(diào)用時(shí)序 (TCP)

    

 無(wú)連接的套接字系統(tǒng)調(diào)用時(shí)序(UDP)

 

二、TCP協(xié)議的Socket實(shí)例

服務(wù)端 后臺(tái)代碼:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.IO;
  7 using System.Linq;
  8 using System.Net;
  9 using System.Net.Sockets;
 10 using System.Text;
 11 using System.Threading;
 12 using System.Threading.Tasks;
 13 using System.Windows.Forms;
 14 
 15 namespace Socket通信
 16 {
 17     public partial class Form1 : Form
 18     {
 19 
 20         public Form1()
 21         {
 22             InitializeComponent();
 23             TextBox.CheckForIllegalCrossThreadCalls = false;
 24 
 25         }
 26         Socket socketSend;
 27         Thread threadWatch = null; // 負(fù)責(zé)監(jiān)聽(tīng)客戶(hù)端連接請(qǐng)求的 線(xiàn)程;
 28         Socket socketWatch = null;
 29 
 30 
 31         /// <summary>
 32         /// 監(jiān)聽(tīng)客戶(hù)端請(qǐng)求的方法;
 33         /// </summary>
 34         void WatchConnecting()
 35         {
 36             try
 37             {
 38                 while (true)  // 持續(xù)不斷的監(jiān)聽(tīng)客戶(hù)端的連接請(qǐng)求;
 39                 {
 40                     // 開(kāi)始監(jiān)聽(tīng)客戶(hù)端連接請(qǐng)求,Accept方法會(huì)阻斷當(dāng)前的線(xiàn)程;
 41                     Socket sokConnection = socketWatch.Accept(); 
 42                     // 一旦監(jiān)聽(tīng)到一個(gè)客戶(hù)端的請(qǐng)求,就返回一個(gè)與該客戶(hù)端通信的 套接字;
 43                     // 向列表控件中添加客戶(hù)端的IP信息;
 44                     lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());
 45                     ShowMsg("客戶(hù)端連接成功!");
 46                     //開(kāi)啟一個(gè)新線(xiàn)程,執(zhí)行接收消息方法
 47                     Thread r_thread = new Thread(Received);
 48                     r_thread.IsBackground = true;
 49                     r_thread.Start(sokConnection);
 50                 }
 51             }
 52             catch (Exception e)
 53             {
 54                 ShowMsg("異常:" + e.Message);
 55             }
 56 
 57         }
 58         /// <summary>
 59         /// 服務(wù)器端不停的接收客戶(hù)端發(fā)來(lái)的消息
 60         /// </summary>
 61         /// <param name="o"></param>
 62         void Received(object o)
 63         {
 64             try
 65             {
 66                  socketSend = o as Socket;
 67                 while (true)
 68                 {
 69                     //客戶(hù)端連接服務(wù)器成功后,服務(wù)器接收客戶(hù)端發(fā)送的消息
 70                     // 定義一個(gè)3M的緩存區(qū);
 71                     byte[] buffer = new byte[1024 * 1024 * 3];
 72                     //實(shí)際接收到的有效字節(jié)數(shù)
 73                     // 將接受到的數(shù)據(jù)存入到輸入  buffer中;
 74                     int len = socketSend.Receive(buffer);
 75                     if (len == 0)
 76                     {
 77                         break;
 78                     }
 79                     string str = Encoding.UTF8.GetString(buffer, 0, len);
 80                     ShowMsg("接收到的客戶(hù)端數(shù)據(jù):" + socketSend.RemoteEndPoint + ":" + str);
 81                     Send("服務(wù)端接收成功(" + str + "");
 82 
 83                 }
 84             }
 85             catch (Exception e)
 86             {
 87                 ShowMsg("異常:" + e.Message);
 88             }
 89         }
 90         /// <summary>
 91         /// 服務(wù)器向客戶(hù)端發(fā)送消息
 92         /// </summary>
 93         /// <param name="str"></param>
 94         void Send(string str)
 95         {
 96             byte[] buffer = Encoding.UTF8.GetBytes(str);
 97             socketSend.Send(buffer);
 98 
 99         }
100         void ShowMsg(string str)
101         {
102             txtMsg.AppendText(str + "\r\n");
103         }
104         private void button1_Click_1(object sender, EventArgs e)
105         {
106             // 創(chuàng)建負(fù)責(zé)監(jiān)聽(tīng)的套接字,注意其中的參數(shù);
107             socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
108             // 獲得文本框中的IP對(duì)象;
109             IPAddress address = IPAddress.Parse(txtIp.Text.Trim());
110             // 創(chuàng)建包含ip和端口號(hào)的網(wǎng)絡(luò)節(jié)點(diǎn)對(duì)象;
111             IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
112             try
113             {
114                 // 將負(fù)責(zé)監(jiān)聽(tīng)的套接字綁定到唯一的ip和端口上;
115                 socketWatch.Bind(endPoint);
116             }
117             catch (SocketException se)
118             {
119                 MessageBox.Show("異常:" + se.Message);
120                 return;
121             }
122             // 設(shè)置監(jiān)聽(tīng)隊(duì)列的長(zhǎng)度;
123             socketWatch.Listen(10);
124             // 創(chuàng)建負(fù)責(zé)監(jiān)聽(tīng)的線(xiàn)程;
125             threadWatch = new Thread(WatchConnecting);
126             threadWatch.IsBackground = true;
127             threadWatch.Start();
128             ShowMsg("服務(wù)器啟動(dòng)監(jiān)聽(tīng)成功!");
129         }
130     }
131 }
Socket_server

客戶(hù)端 后臺(tái)代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 using System.Net;
11 using System.Net.Sockets;
12 using System.Threading;
13 
14 
15 namespace Socket通信客戶(hù)端
16 {
17     public partial class Socket_client : Form
18     {
19         public Socket_client()
20         {
21             InitializeComponent();
22             CheckForIllegalCrossThreadCalls = false;
23         }
24         Socket socketSend;
25         void ShowMsg(string str)
26         {
27             txtMsg.AppendText(str + "\r\n");
28         }
29         /// <summary>
30         /// 接收服務(wù)端返回的消息
31         /// </summary>
32         void Received()
33         {
34             while (true)
35             {
36                 try
37                 {
38                     byte[] buffer = new byte[1024 * 1024 * 3];
39                     //實(shí)際接收到的有效字節(jié)數(shù)
40                     int len = socketSend.Receive(buffer);
41                     if (len == 0)
42                     {
43                         continue;
44                     }
45                     string str = Encoding.UTF8.GetString(buffer, 0, len);
46                     ShowMsg("接收到的服務(wù)端數(shù)據(jù):" + socketSend.RemoteEndPoint + ":" + str);
47                 }
48                 catch
49                 {
50                     MessageBox.Show("接收失敗,請(qǐng)檢查服務(wù)端是否斷開(kāi)!");
51                     return;
52                 }
53             }
54         }
55 
56         private void btnDisconnect_Click(object sender, EventArgs e)
57         {
58             socketSend.Close();
59             ShowMsg("連接已經(jīng)斷開(kāi)!");
60         }
61         void Send(string str)
62         {
63             byte[] buffer = Encoding.UTF8.GetBytes(str);
64             socketSend.Send(buffer);
65         }
66     }
67 }
Socket_client

三、UDP協(xié)議的Socket實(shí)例

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SimpleUdpSrvr
{
    class Program
    {
        static void Main(string[] args)
        {
            int recv;
            byte[] data = new byte[1024];
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);//定義一網(wǎng)絡(luò)端點(diǎn)
            Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);//定義一個(gè)Socket
            newsock.Bind(ipep);//Socket與本地的一個(gè)終結(jié)點(diǎn)相關(guān)聯(lián)
            Console.WriteLine("Waiting for a client..");

            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);//定義要發(fā)送的計(jì)算機(jī)的地址
            EndPoint Remote = (EndPoint)(sender);//
            recv = newsock.ReceiveFrom(data, ref Remote);//接受數(shù)據(jù)           
            Console.WriteLine("Message received from{0}:", Remote.ToString());
            Console.WriteLine(Encoding.ASCII.GetBytes(data,0,recv));

            string welcome = "Welcome to my test server!";
            data = Encoding.ASCII.GetBytes(welcome);
            newsock.SendTo(data, data.Length, SocketFlags.None, Remote);
            while (true)
            {
                data = new byte[1024];
                recv = newsock.ReceiveFrom(data, ref Remote);
                Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
                newsock.SendTo(data, recv, SocketFlags.None, Remote);
            }
        }
    }
}
UDPServer
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SimpleUdpClient
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] data = new byte[1024];//定義一個(gè)數(shù)組用來(lái)做數(shù)據(jù)的緩沖區(qū)
            string input, stringData;
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            string welcome = "Hello,are you there?";
            data = Encoding.ASCII.GetBytes(welcome);
            server.SendTo(data, data.Length, SocketFlags.None, ipep);//將數(shù)據(jù)發(fā)送到指定的終結(jié)點(diǎn)

            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)sender;
            data = new byte[1024];
            int recv = server.ReceiveFrom(data, ref Remote);//接受來(lái)自服務(wù)器的數(shù)據(jù)

            Console.WriteLine("Message received from{0}:", Remote.ToString());
            Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
            while (true)//讀取數(shù)據(jù)
            {
                input = Console.ReadLine();//從鍵盤(pán)讀取數(shù)據(jù)
                if (input == "text")//結(jié)束標(biāo)記
                {
                    break;
                }
                server.SendTo(Encoding.ASCII.GetBytes(input), Remote);//將數(shù)據(jù)發(fā)送到指定的終結(jié)點(diǎn)Remote
                data = new byte[1024];
                recv = server.ReceiveFrom(data, ref Remote);//從Remote接受數(shù)據(jù)
                stringData = Encoding.ASCII.GetString(data, 0, recv);
                Console.WriteLine(stringData);
            }
            Console.WriteLine("Stopping client");
            server.Close();
        }
    }
}     
UDPClient

   上面的示例只是簡(jiǎn)單的應(yīng)用了socket來(lái)實(shí)現(xiàn)通信,你也可以實(shí)現(xiàn)異步socket、IP組播 等等。

     MS還為我們提供了幾個(gè)助手類(lèi):TcpClient類(lèi)、TcpListener類(lèi)、UDPClient類(lèi)。這幾個(gè)類(lèi)簡(jiǎn)化了一些操作,所以你也可以利用這幾類(lèi)來(lái)寫(xiě)上面的代碼,但我個(gè)人還是比較習(xí)慣直接用socket來(lái)寫(xiě)。
      既然快寫(xiě)完了,那我就再多啰嗦幾句。在需要即時(shí)響應(yīng)的軟件中,我個(gè)人更傾向使用UDP來(lái)實(shí)現(xiàn)通信,因?yàn)橄啾萒CP來(lái)說(shuō),UDP占用更少的資源,且響應(yīng)速度快,延時(shí)低。至于UDP的可靠性,則可以通過(guò)在應(yīng)用層加以控制來(lái)滿(mǎn)足。當(dāng)然如果可靠性要求高的環(huán)境下,還是建議使用TCP。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多