工具: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控件