C#编程与网络编程
用C#创建一个简单的控制台程序
1.在VS2017/2019下创建一个C#项目
这里的文件名字和存储地址都是自己设置
源代码如下
using System;
namespace App1
{
class Program
{
static void Main(string[] args)
{
for (int i = 1; i <= 50; i++)
{
Console.WriteLine("hello cqjtu!重交物联2018级");
}
Console.ReadLine();
}
}
}
创建好之后我们就可以编写自己的程序代码,在这里我写的是输出50行“hello cqjtu!重交物联2018级”,编写好之后直接编译,运行。
我们使用Console.ReadLine()方法从控制台读取任何行,通过输入此行代码,程序将等待并且不会立即退出。该程序将等待用户输入任何字符然后回车。
二、用C#编写一个简单的Form窗体程序
创建一个窗口应用程序
在新建的项目中作为客户端输入以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
//提示信息
Console.WriteLine("按下任意按键开始发送...");
Console.ReadKey();
int m;
//做好链接准备
UdpClient client = new UdpClient(); //实例一个端口
IPAddress remoteIP = IPAddress.Parse("10.60.189.252"); //这个IP是我室友的电脑
int remotePort = 11000; //设置端口号
IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort); //实例化一个远程端点
for (int i = 0; i < 50; i++)
{
//要发送的数据:第n行:hello cqjtu!重交物联2018级
string sendString = null;
sendString += "第";
m = i + 1;
sendString += m.ToString();
sendString += "行:hello cqjtu!重交物联2018级";
//定义发送的字节数组
//将字符串转化为字节并存储到字节数组中
byte[] sendData = null;
sendData = Encoding.Default.GetBytes(sendString);
client.Send(sendData, sendData.Length, remotePoint);//将数据发送到远程端点
}
client.Close();//关闭连接
//提示信息
Console.WriteLine("");
Console.WriteLine("数据发送成功,按任意键退出...");
System.Console.ReadKey();
}
}
}
在室友电脑上同样新建一个控制台程序作为服务器端输入以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
class Program
{
static void Main(string[] args)
{
int result;
string str = "第50行:hello cqjtu!重交物联2018级";
UdpClient client = new UdpClient(11000);
string receiveString = null;
byte[] receiveData = null;
//实例化一个远程端点,IP和端口可以随意指定,等调用client.Receive(ref remotePoint)时会将该端点改成真正发送端端点
IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);
Console.WriteLine("正在准备接收数据...");
while (true)
{
receiveData = client.Receive(ref remotePoint);//接收数据
receiveString = Encoding.Default.GetString(receiveData);
Console.WriteLine(receiveString);
result = String.Compare(receiveString, str);
if (result == 0)
{
break;
}
}
client.Close();//关闭连接
Console.WriteLine("");
Console.WriteLine("数据接收完毕,按任意键退出...");
System.Console.ReadKey();
}
}
}
两台电脑启动编译,运行
这里自己设置一个窗口
源代码
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();
}
}
}
}
三、用wireshark抓包软件抓取网络包
安装Wireshark
安装过后
这里我们双击本地连接,就能发现软件在不断的抓取包
1.从跟踪中选择一个 UDP 数据包。从此数据包中,确定 UDP 标头中有多少字段,并为这些字段命名,抓取一个包
2.UDP 的标头有 4 个字段,一共 8 byte,各字段分别为:
*Source Port:源端口号
*Destination Port:目的端口号
*Length:长度
*Checksum:校验和
3. 通过查询 Wireshark 的数据包内容字段中显示的信息,确定每个 UDP 报头字段的长度。
每个部分都是 2 byte,因此 UDP 报头为 8 byte = 64 bit
4. UDP 有效负载中可包含的最大字节数是多少?
简单地说,有效负载就是可变长度的数据部分。由于 Length 字段占 2byte = 8888bit,并且其中 8 byte 是 UDP 首部信息。因此有效载荷 = 8888 - 8 = 8880bit。
5. 最大可能的源端口号是多少?
两个 Port 字段占 2 byte = 8894bit,同时端口号从 0 开始算,因此最大端口号 = 216 - 1 = 。
6.UDP的协议号
总结
本次实验做的事情比较多,很多东西还需要多练
参考:https://blog.youkuaiyun.com/qq