C#編程和網絡編程入門

工具:vs2017

html

1、用C#編寫一個命令行/控制檯hello world程序

控制檯應用

打開vs2017,新建一個C#控制檯應用
寫入下列代碼
編程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{ 
    class Program
    { 
        static void Main(string[] args)
        { 
            string s = "hello cqjtu!重交物聯2018級";
            //由於下面要使用StringBuilder的Append函數
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 50; i++)
            { 
                sb.Append(s);
            }
            //將StringBuilder轉換爲string,並寫入
            Console.WriteLine(sb.ToString());
            //控制檯顯示
            Console.ReadLine();
        }
    }
}

顯示效果
在這裏插入圖片描述
c#

命令行編程

1.配置環境變量
找到csc.exe所在文件位置,將其路徑加入環境變量path中
例如個人csc.exe在D:\visual studio install\MSBuild\15.0\Bin\Roslyn下
再打開命令行窗口,輸入csc,出現下圖效果即爲成功
在這裏插入圖片描述
找到helloworld程序.cs文件所在文件所在位置,用cmd快速進入當前路徑
在這裏插入圖片描述
編譯.cs文件爲.exe可執行文件






windows

csc Program.cs

執行數組

Program.exe

在這裏插入圖片描述

2、網絡UDP編程

實現功能:打開程序向另外一臺電腦發送上述helloworld程序打印的信息
UDP編程是面向無鏈接的,不須要在客戶端和服務端之間創建鏈接
打開vs2017新建c#控制檯項目項目udp_server,將udp_server中的Program.c中的代碼替換爲:

服務器

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDP
{ 
    class Program
    { 
        static void Main(string[] args)
        { 
            int recv;
            byte[] data = new byte[1024];

            //獲得本機IP,設置TCP端口號 
            IPEndPoint ip = new IPEndPoint(IPAddress.Any, 8001);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            //綁定網絡地址
            server.Bind(ip);

            Console.WriteLine("This is a Server, host name is {0}", Dns.GetHostName());

            //等待客戶機鏈接
            Console.WriteLine("Waiting for a client");

            //獲得客戶機IP
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)(sender);
            recv = server.ReceiveFrom(data, ref Remote);
            Console.WriteLine("Message received from {0}: ", Remote.ToString());
            Console.WriteLine(Encoding.Default.GetString(data, 0, recv));

            //客戶機鏈接成功後,發送信息
            string welcome = "鏈接成功 ";

            //字符串與字節數組相互轉換
            data = Encoding.Default.GetBytes(welcome);

            //發送信息 
            server.SendTo(data ,Remote);



            while (true)
            { 
                data = new byte[1024];
                //發送接收信息
                //從客戶機接受消息
                recv = server.ReceiveFrom(data, ref Remote);
                //將字節流信息轉換爲字符串
                string Data = Encoding.Default.GetString(data, 0, recv);
                //將字符串輸出到屏幕上
                Console.WriteLine(Data);
                // Console.WriteLine(Encoding.Default.GetString(data, 0, recv));
                /* //定義字符串input string input; //讀取屏幕上的字符串 input = Console.ReadLine(); if (input == "exit") break; //將input發送至客戶機 server.SendTo(Encoding.Default.GetBytes(input),Remote);*/
            }
            server.Close();
        }

    }
}

關閉當前項目並新建c#控制檯項目udp_client,將udp_client中的Program.c中的代碼替換爲:網絡

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDPClient
{ 
    class Program
    { 
        static void Main(string[] args)
        { 
            byte[] data = new byte[1024];
            string input;

            //構建TCP 服務器
            Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());

            //設置服務IP,設置TCP端口號
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);

            //定義網絡類型,數據鏈接類型和網絡協議UDP
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            string welcome = "鏈接成功!";
            //字符串與字節數組相互轉換
            data = Encoding.Default.GetBytes(welcome);
            //發送信息
            client.SendTo(data,ip);

            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)sender;

            data = new byte[1024];
            //對於不存在的IP地址,加入此行代碼後,能夠在指定時間內解除阻塞模式限制
            //接受信息
            int recv = client.ReceiveFrom(data, ref Remote);
            //輸出服務端ip
            Console.WriteLine("Message received from {0}: ", Remote.ToString());
            //輸出接受到的信息
            Console.WriteLine(Encoding.Default.GetString(data, 0, recv));
            while (true)
            { 
                //讀取屏幕的字符串存入input中
                input = Console.ReadLine();
                if (input == "exit")
                    break;
                //將input中的字符串發送至服務端
                for (int i=0;i<50;i++)
                { 
                    client.SendTo(Encoding.Default.GetBytes(input), Remote);
                }

                /* data = new byte[1024]; //將接受自服務端的信息存入recv中 recv = client.ReceiveFrom(data, ref Remote); //將字節流轉爲字符串 string Data = Encoding.Default.GetString(data, 0, recv); //將Date中的數據打印到屏幕上 Console.WriteLine(Data);*/
            }
            //輸入exit後,屏幕打印下列字符串
            Console.WriteLine("Stopping Client.");
            //關閉服務端
            client.Close();
        }

    }
}

在這裏插入圖片描述
1.注意箭頭所指ip爲服務端的電腦ip,可在cmd窗口中 ipconfig 命令獲得
2.一臺電腦運行服務端,一臺電腦運行客戶端,兩臺電腦必須處於同一局域網下
3.上述程序只實現了客戶端向服務端發送數據
效果
在這裏插入圖片描述




函數

3、用VS2017 的C#編寫一個簡單的Form窗口程序

打開vs2017建立一個c# windows窗體應用frame_udp_server,
窗口控件:
listBpx
textBox
button
label
在這裏插入圖片描述
將Form1.cs中的內容用下列代替換:






工具

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace frame_udp_server
{ 
    public partial class Form1 : Form
    { 
        private UdpClient receiveUdpClient;//接收用
        private UdpClient sendUdpClient;//發送用
        private const int port = 8001;//和本機綁定的端口號
        IPAddress ip = IPAddress.Parse("192.168.43.2");//本機ip
        IPAddress remoteip = IPAddress.Parse("192.168.43.151");//遠程主機ip
        public Form1()
        { 
            InitializeComponent();
            
            CheckForIllegalCrossThreadCalls = false;
            /* //獲取本機可用IP地址 IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName()); foreach (IPAddress ipa in ips) { if (ipa.AddressFamily == AddressFamily.InterNetwork) { ip = ipa; break; } } */
            //爲了在同一臺機器調試,此IP也做爲默認遠程IP
            //IPAddress remoteip = IPAddress.Parse("192.168.43.151");

        }

        private void Form1_Load(object sender, EventArgs e)
        { 
            //建立一個線程接收遠程主機發來的信息
            Thread myThread = new Thread(ReceiveData);
            myThread.IsBackground = true;
            myThread.Start();
        }

        //接收數據
        private void ReceiveData()
        { 
            IPEndPoint local = new IPEndPoint(ip, port);
            receiveUdpClient = new UdpClient(local);
            IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            { 
                try
                { 
                    //關閉udpClient 時此句會產生異常
                    byte[] receiveBytes = receiveUdpClient.Receive(ref remote);
                    string receiveMessage = Encoding.Unicode.GetString(
                        receiveBytes, 0, receiveBytes.Length);
                    listBox1.Items.Add("收到的消息:" + receiveMessage);
                }
                catch
                { 
                    break;
                }
            }
        }
        //點擊發送按鈕發送數據
        private void button1_Click(object sender, EventArgs e)
        { 
            //remoteip = IPAddress.Parse(txt_IPAddress.Text);
            Thread myThread = new Thread(SendMessage);
            myThread.IsBackground = true;
            myThread.Start(textBox2.Text);
        }
        //發送消息
        private void SendMessage(object obj)
        { 
            string message = (string)obj;
            sendUdpClient = new UdpClient(0);
            byte[] bytes = Encoding.Unicode.GetBytes(message);
            IPEndPoint iep = new IPEndPoint(remoteip, port);
            try
            { 
                sendUdpClient.Send(bytes, bytes.Length, iep);
                listBox1.Items.Add("發送的消息:" + message);
                textBox2.Clear();
            }
            catch (Exception ex)
            { 
                listBox1.Items.Add("發送出錯:" + ex.Message);
            }
        }
        delegate void AddItemDelegate(ListBox listbox, string text);
        private void AddItem(ListBox listbox, string text)
        { 
            if (listbox.InvokeRequired)
            { 
                AddItemDelegate d = AddItem;
                //Control.Invoke 方法 (Delegate, Object[]):
                //在擁有控件的基礎窗口句柄的線程上,用指定的參數列表執行指定委託。
                listbox.Invoke(d, new object[] {  listbox, text });
            }
            else
            { 
                //Add:動態的添加列表框中的項
                listbox.Items.Add(text);

                //SelectedIndex屬性獲取單項選擇ListBox中當前選定項的位置
                //Count:列表框中條目的總數
                listbox.SelectedIndex = listbox.Items.Count - 1;

                //調用此方法等效於將 SelectedIndex 屬性設置爲-1。 
                //可使用此方法快速取消選擇列表中的全部項。
                listbox.ClearSelected();
            }
        }
        delegate void ClearTextBoxDelegate();
        private void ClearTextBox()
        { 
            if (textBox2.InvokeRequired)
            { 
                ClearTextBoxDelegate d = ClearTextBox;
                textBox2.Invoke(d);
            }
            else
            { 
                textBox2.Clear();
                textBox2.Focus();
            }
        }




    }
}

注意:
我這裏測試用的ip是我開手機熱點造成的一個局域網裏兩臺電腦的ip
簡言之,這個程序和上面的控制檯udp程序同樣,要聯通就必須處於同一局域網,
在這裏插入圖片描述
關閉項目frame_udp_server,新建c# windows窗體應用frame_udp_client,代碼除了上面圖片中本機ip和遠程主機ip不一樣外,其他都相同。
測試效果:
在這裏插入圖片描述
下面是使用wireshark 抓包軟件抓到的這個程序發送的數據
在這裏插入圖片描述







測試

在這裏插入圖片描述
1.UDP 的標頭有 4 個字段,一共 8 byte,各字段分別爲:
*Source Port:源端口號
*Destination Port:目的端口號
*Length:長度
*Checksum:校驗和




2.經過查詢 Wireshark 的數據包內容字段中顯示的信息,能夠肯定每一個 UDP 報頭字段的長度。
每一個部分都是 2 byte,所以 UDP 報頭爲 8 byte = 64 bit。
3.長度字段指示了在 UDP 報文段中的字節數(首部 + 數據),這是由於數據字段的長度在一個 UDP 段中不一樣於在另外一個段中,所以須要一個明確的長度。
在這裏插入圖片描述


如圖,報文長度爲26byte,加上首部的8byte恰好是Length的長度

有效負載是被傳輸數據中的一部分,而這部分纔是數據傳輸的最基本的目的,和有效負載一同被傳送的數據還有:數據頭或稱做元數據,有時候也被稱爲開銷數據,這些數據用來輔助數據傳輸。——百度百科

4.簡單地說,有效負載就是可變長度的數據部分。因爲 Length 字段佔 2byte = 65536 bit,而且其中 8 byte 是 UDP 首部信息。所以有效載荷 = 65536 - 8 = 65528 bit。
5.最大可能的源端口號是多少?
兩個 Port 字段佔 2 byte = 65536 bit,同時端口號從 0 開始算,所以最大端口號 = 65536 - 1 = 65535。
6.如圖,udp協議號爲17,十六進制爲 0x11。
在這裏插入圖片描述
7.在抓到這個包的同時,咱們確定能夠找到回覆的包,兩個包中源端口和目的端口應該相反




參考博客:

C# UDP 聊天窗口程序
c#窗體應用----textbox控件
關於IPAddress類實例化時參數的問題。
線程間操做無效
c# ListBox控件

相關文章
相關標籤/搜索