工具:vs2017
目錄
- 一、用C#撰寫一個命令列/控制臺hello world程式
- 控制臺應用
- 命令列編程
- 二、網路UDP編程
- 三、用VS2017 的C#撰寫一個簡單的Form視窗程式
- 參考博客:
一、用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();
}
}
}
顯示效果

命令列編程
1.配置環境變數
找到csc.exe所在檔案位置,將其路徑加入環境變數path中
例如我的csc.exe在D:\visual studio install\MSBuild\15.0\Bin\Roslyn下
再打開命令列視窗,輸入csc,出現下圖效果即為成功

找到helloworld程式.cs檔案所在檔案所在位置,用cmd快速進入當前路徑

編譯.cs檔案為.exe可執行檔案
csc Program.cs
執行
Program.exe

二、網路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.上述程式只實作了客戶端向服務端發送資料
效果

三、用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控制元件
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/198705.html
標籤:其他
