学习目标:
1.用C#编写一个命令行/控制台hello world程序.
2.用VS2015/2017 的C#编写一个简单的Form窗口程序
3.安装wireshark 抓包软件,抓取上述程序发送的网络包,对数据帧结构进行分析。
环境配置
树莓派需要先配置好C#的运行环境安装dotnet,详情见参考资料【树莓派安装C#运行环境】
Download .NET Core 3.0
Download .NET Core
提示:C#安装的.NET Core版本需要与C#发布所使用的版本一致,否则会报错
我最开始安装的是3.0版本的,发现版本不匹配,之后又安装了2.0
但是看了下我的VS安装器里面貌似只有2.0的
用C#编写一个命令行/控制台hello world程序:
编译程序并在树莓派上运行
1.用Advanced_IP_Scanner查看到一个名字叫Raspberry Pi的计算机名称,就是树莓派的,记下他的IP地址
2.Xshell里面新建会话pi2-Android
输入用户名和密码后保存并连接
编写consoleapp1
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("192.168.43.242"); //接收方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();
}
}
}
consoleapp2
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();
}
}
}
发布app2
使用xshell6+xftp6上传程序
consoleapp2传输完成
回到在xshell中,进入目录输入:cd ConsoleApp2/
运行程序: dotnet ConsoleApp2.dll
成功
wireshark 抓包
打开wireshark
因为不知道程序走的哪个接口,通过ipconfig寻找和树莓派在同样一个子网的接口
发现是无线局域网适配器 本地连接* 2这一接口,网络号同为 192.168.137
再次运行程序,开始抓包
数据发送完毕
分析抓到的包显示,3-52编号的UDP协议的包为刚刚发送的数据,使用过滤器过滤udp协议的包
包中
协议为UDP
TTL=64
source为本机ipconfig得到的IP
destination为树莓派的ip
并有源Mac地址(本机)和目的Mac地址(树莓派)
用VS2015/2017 的C#编写一个简单的Form窗口程序:
首先创建两个项目:
发送端创建一个windows窗体应用
接受端创建一个控制台应用
代码
发送端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string sendStr = textBox1.Text;
byte[] bs = Encoding.UTF8.GetBytes(sendStr);
IPEndPoint iep1 = new IPEndPoint(IPAddress.Parse("192.168.137.31"), 3000);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
socket.SendTo(bs, iep1);
socket.Close();
label1.Text = "发送完毕!!\r\n";
}
private void label1_Click(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
接受端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string receiveString = null;
byte[] receiveData = new byte[1024 * 64];
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 3000);
sock.Bind(iep);
EndPoint ep = (EndPoint)iep;
Console.WriteLine("正在准备接收数据...");
sock.Receive(receiveData);
receiveString = Encoding.UTF8.GetString(receiveData);
Console.WriteLine(receiveString);
sock.Close();//关闭连接
Console.WriteLine("");
Console.WriteLine("数据接收完毕,按任意键退出...");
System.Console.ReadKey();
}
}
}
注意:
Receive方法将数据读入 buffer 参数,并返回成功读取的字节数。 可 Receive 从面向连接的套接字和无连接套接字调用。
此重载只要求你提供接收缓冲区。 缓冲区偏移量默认为0,大小默认为 buffer 参数的长度, SocketFlags 值默认为 None 。
故 buffer参数 receivData长度必须预设好,否则调用 sock.Receive(receiveData);时会报错
运行:
发送成功!
wireshark抓包:
过滤出UDP协议的包,在其中找到source为 192.168.137.1的
端口号为3000的包
数据内容一致
且MAC地址与上一实验一致
参考资料:
C# .net2.0 套接字编程实例 UDP TCP通信
树莓派安装C#运行环境
C#网络UDP编程套接字与Wireshark抓包(参考代码)
Socket.Receive 方法(微软官方)
UDP简单桌面同步