一、控制台程序使用 UDP 通信
本内容为用C#、Java或python编写一个命令行/控制台的简单hello world程序,实现如下功能:在屏幕上连续输出50行“hello cqjtu!重交物联2019级”;同时打开一个网络UDP 套接字,向另一台室友电脑发送这50行消息。
程序实现功能: 从客户端循环发送多条数据,服务器端接收多条数据。
接下来我们创建一个新的 C# 控制台程序。
1)创建新项目
- 打开 VS2019 ,点击 “ 创建新项目 ”
- 选择 “ 控制台应用(.NET Framework) ” ,然后点击 “ 下一步 ”。
- 编辑 “ 项目名称 ” ,选择程序保存位置,然后点击 “ 创建 ”。
- 创建完毕就如下显示。
2)编写代码
- 在 Main 函数内书写如下的代码(功能:连续输出 50 行数据)。
for(int i = 0; i < 50; i++)
{
Console.WriteLine("第{0}行:hello cqjtu!重交物联2019级", (i + 1));
}
System.Console.ReadKey();
- 编译输出结果。
这一部分编写一个简单的 UDP 通信实例,下一部分写个更复杂一点的 TCP 通信。
目前最普遍的服务模式是 C/S 模式,所以需要一个客户端 client 和一个服务端 Server ,来实现通信。
比如我现在在我的电脑上运行一个客户端代码,在我室友的电脑上运行一个服务端的代码,就可以实现通信功能。当然也可以在自己电脑上开两个VS来运行客户端和服务端。
- 使用 VS2019 创建一个新项目 client ,并将下列代码复制粘贴进去。(注意头文件!!!使用网络协议需要引入头文件 .Net 和 .Net.Sockets)
客户端:
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.0.179"); //假设发送给这个IP
int remotePort = 11000; //设置端口号
IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort); //实例化一个远程端点
for(int i = 0; i < 50; i++)
{
//要发送的数据:第n行:hello cqjtu!重交物联2019级
string sendString = null;
sendString += "第";
m = i+1;
sendString += m.ToString();
sendString += "行:hello cqjtu!重交物联2019
> 这里是引用
级";
//定义发送的字节数组
//将字符串转化为字节并存储到字节数组中
byte[] sendData = null;
sendData = Encoding.Default.GetBytes(sendString);
client.Send(sendData, sendData.Length, remotePoint);//将数据发送到远程端点
}
client.Close();//关闭连接
//提示信息
Console.WriteLine("");
Console.WriteLine("数据发送成功,按任意键退出...");
System.Console.ReadKey();
}
}
}
这里的IP地址用自己的!!!!如果不知道自己IP地址用win+r输入cmd然后输入命令ipconfig就能看到自己的IP地址了
打开另外一个VS,使用 VS2019 创建一个新项目 server,并将下列代码复制粘贴进去。
服务器端:
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!重交物联2019级";
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();
}
}
}
3)编译结果
客户端:
服务端:
二、Form窗口程序使用 TCP 通信
本部分内容:用VS2017/2019 的C#编写一个简单的Form窗口程序,有一个文本框 textEdit和一个发送按钮button,运行程序后,可以在文本框里输入文字,如“hello cqjtu!重交物联2019级”,点击button,将这些文字发送给室友电脑,采用UDP套接字;
程序实现功能: 从客户端发送多条数据,服务器端接收多条数据,服务器端反馈发送信息给客户端,客户端收到并显示出来。
接下来,我们创建一个新的 C# Form 窗口程序。
1)创建新项目
- 选中 “ Windows 窗体应用 ” ,再点击 “ 下一步 ”。
- 设置项目名称、保存位置,再点击 “ 创建 ” 。
- 创建完毕。
2)设计图形界面
摆放控件:
- 首先往图形界面内拖动控件并进行摆放,如下图所示。
- 从工具箱内拖 2 个 TextBox 和 1 个 Button 控件。
注:刚拖出来的 TextBox 只能输入一行,只能横着拖,不能竖着拖,不用担心,看看下面的设置属性,就可以设计出如下的界面了。
设置消息显示界面属性:
- 选中一个 TextBox ,并点击黑色的小三角按钮,可以将单行文本框设置为多行文本框。
- 添加垂直滚动条:找到 ScrollBars 属性,设置参数为 Vertical 。
- 设置边界样式:找到 BorderStyle ,参数设置为 FixedSingle 。
- 设置消息显示界面的 TextBox 不可编辑:找到 Enabled 属性,参数设为 False 。
除此之外,你还可以根据设置消息输入框的文本样式来设置消息显示界面内的文本样式。
设置发送消息按钮属性: - 左键点击选中按钮,找到 Text 属性,参数输入为 “ 发送 ” ,则控件上就会显示输入的字样。
设置窗体属性:- 左击窗体选中它,在右下角的属性中找到 Text 属性,编辑为 “ 客户端 ” ,然后窗体的左上角,就显示为 “ 客户端 ”。
- 紧接着,有个 AcceptButton 属性,下拉框选中这个 button1 按钮,设置完这个属性后,当我们最后执行这个程序后,按下回车键 = 点击这个按钮。
至此,控件的一些简单属性就设置完毕了。
3)编写代码
双击图形界面的按钮后,VS2019 会自动的转到代码编辑区域。
红色方框后就是我们双击按钮后,要编写触发事件执行过程的代码,也就是点击按钮后,就会执行这个函数体。
- 在 button1_Click 函数内复制粘贴如下代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
try
{
/*
* 显示当前时间
*/
string str = "The current time: ";
str += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
textBox2.AppendText(str + Environment.NewLine);
/*
* 做好连接准备
*/
int port = 2000;
string host = "192.168.0.179";//我的IP地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndPoint实例
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket
/*
* 开始连接
*/
str = "Connect to server...";
textBox2.AppendText(str + Environment.NewLine);
c.Connect(ipe);//连接到服务器
/*
*发送消息
*/
string sendStr = textBox1.Text;
str = "The message content: " + sendStr;
textBox2.AppendText(str + Environment.NewLine);
byte[] bs = Encoding.UTF8.GetBytes(sendStr);
str = "Send the message to the server...";
textBox2.AppendText(str + Environment.NewLine);
c.Send(bs, bs.Length, 0);//发送信息
/*
* 接收服务器端的反馈信息
*/
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
str = "The server feedback: " + recvStr;//显示服务器返回信息
textBox2.AppendText(str + Environment.NewLine);
/*
* 关闭socket
*/
c.Close();
}
catch (ArgumentNullException f)
{
string str = "ArgumentNullException: " + f.ToString();
textBox2.AppendText(str + Environment.NewLine);
}
catch (SocketException f)
{
string str = "ArgumentNullException: " + f.ToString();
textBox2.AppendText(str + Environment.NewLine);
}
textBox2.AppendText("" + Environment.NewLine);
textBox1.Text = "";
}
}
}
接下来开始编写服务器端代码:
- 根据第二部分: “ 控制台程序使用 UDP 通信 ” 创建一个新的控制台程序,这里就不再演示了。
- 复制下面 main 函数内的代码,并粘贴进你自己的 main 函数体内。
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)
{
/*
* 做好连接准备
*/
int i = 0;
int port = 2000;
string host = "192.168.0.179";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket类
s.Bind(ipe);//绑定2000端口
/*
* 循环监听并处理消息
*/
while (true)
{
i++;
try
{
Console.Write("Perform operations {0} :",i);
Console.WriteLine("\t-----------------------------------------------");
s.Listen(0);//开始监听
Console.WriteLine("1. Wait for connect...");
/*
* 实例一个新的socket端口
*/
Socket temp = s.Accept();//为新建连接创建新的Socket。
Console.WriteLine("2. Get a connect");
/*
* 接收客户端发的消息并做解码处理
*/
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息
recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
Console.WriteLine("3. Server Get Message:{0}", recvStr);//把客户端传来的信息显示出来
/*
* 返回给客户端连接成功的消息
*/
string sendStr = "Ok!Client send message sucessful!";
byte[] bs = Encoding.UTF8.GetBytes(sendStr);
temp.Send(bs, bs.Length, 0);//返回客户端成功信息
/*
* 关闭端口
*/
temp.Close();
Console.WriteLine("4. Completed...");
Console.WriteLine("-----------------------------------------------------------------------");
Console.WriteLine("");
//s.Close();//关闭socket(由于再死循环中,所以不用写,但如果是单个接收,实例socket并完成任务后需关闭)
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
}
}
}
4)编译客户端和服务器端
客户端:
服务器端:
发送结果:
5)抓包分析数据
下面这几个包就是我发送给我电脑上的信息了。
第三行:Internet Protocl Version 4:IPv4协议
第四行:User Datagram Protocol:UDP协议