TCP与UDP的优缺点这里就不说明了。。。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace UDPTestByCore
{
class Program
{
/// <summary>
/// 用于UDP发送的网络服务类
/// </summary>
private static UdpClient udpcSend = null;
static IPEndPoint localIpep = null;
public static void Main(string[] args)
{
Console.Write("IP:");
string ip = Console.ReadLine();
Console.Write("Port:");
int port = int.Parse(Console.ReadLine());
localIpep = new IPEndPoint(IPAddress.Parse(ip), port); // 本机IP,指定的端口号
udpcSend = new UdpClient(localIpep);
StartReceive();
// 实名发送
string msg = null;
while ((msg = Console.ReadLine()) != null)
{
if ("stop" == msg)
{
StopReceive();
udpcSend.Close();
}
else
{
//string[] arr = Console.ReadLine().Split(' ');
Thread thrSend = new Thread(SendMessage);
thrSend.Start(msg);
}
}
Console.ReadKey();
}
/// <summary>
/// 发送信息
/// </summary>
/// <param name="obj"></param>
private static void SendMessage(object obj)
{
try
{
string message = obj.ToString();
string[] array = message.Split(' ');
IPAddress iPAddress = IPAddress.Parse(array[0]);
int port = int.Parse(array[1]);
byte[] sendbytes = Encoding.Unicode.GetBytes(array[2]);
IPEndPoint remoteIpep = new IPEndPoint(iPAddress, port); // 发送到的IP地址和端口号
udpcSend.Send(sendbytes, sendbytes.Length, remoteIpep);
}
catch { }
}
/// <summary>
/// 开关:在监听UDP报文阶段为true,否则为false
/// </summary>
static bool IsUdpcRecvStart = false;
/// <summary>
/// 线程:不断监听UDP报文
/// </summary>
static Thread thrRecv;
private static void StartReceive()
{
if (!IsUdpcRecvStart) // 未监听的情况,开始监听
{
thrRecv = new Thread(ReceiveMessage);
thrRecv.Start();
IsUdpcRecvStart = true;
Console.WriteLine("UDP监听器已成功启动");
}
}
private static void StopReceive()
{
if (IsUdpcRecvStart)
{
thrRecv.Abort(); // 必须先关闭这个线程,否则会异常
IsUdpcRecvStart = false;
Console.WriteLine("UDP监听器已成功关闭");
}
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="obj"></param>
private static void ReceiveMessage(object obj)
{
while (IsUdpcRecvStart)
{
try
{
byte[] bytRecv = udpcSend.Receive(ref localIpep);
string message = Encoding.Unicode.GetString(bytRecv, 0, bytRecv.Length);
Console.WriteLine(string.Format("{0}[{1}]", localIpep, message));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
}
}
}
}
可以同一台电脑使用两个端口号测试。
发送消息格式为 接受端IP 接受端端口号 内容。(空格隔开)
具体可以根据需要修改。
这里只是简单的通讯,但实际使用中我们是不会知道接受端的IP和端口号的,我们可以通过以下方法实现。
1.即时通讯要有状态心跳包,我们可以通过客户端向服务的发送心跳信息时存储客户端对应的IP和端口(至于怎么获取请仔细看上面的代码。。。)自然这种数据存储在Redis等内存数据库中最好了。
2.使用上面代码修改为服务端,原理也比较简单,我们要知道服务端的IP 和端口号。创建一个新的Socket 用来获取状态数据并保存对应客户端的IP和端口号。
3.在客户端获取好友状态数据时获取对应的最新的IP和端口号(至于好友关系大家自己脑补,也比较简单。)。
4.有了IP和端口号还怕发不出消息吗?OK .
其实有人会有疑问:我的电脑是经过路由器的,没有固定IP 和端口号,其实这个可以研究一下网络通信相关的知识。
简单说一下
用户 要访问 百度
大家知道百度的服务器(站点)是有固定IP的,所以用户请求百度是很好理解的,但百度怎么讲返回数据发送给用户呢?因为用户并没有固定的IP。
原理是 举例
用户访问百度时 经过了两个路由器 分别是A 和B
用户在经过A路由器时 A路由器会分配给用户一个唯一的端口号 并携带这些信息去请求B路由器 B路由器同样会给它分配一个端口,接着访问到百度的服务器,服务器将结果数据原路返回,经过B 经过A 直到用户端。。。。。也就是说他们是通过对应的端口号来区分的。