.net 使用TCP模拟UDP广播通信加强广播通信的稳定性
应用场景:当每一台终端开启程序后发出消息,其他终端必须收到消息然后处理
思路1:使用UDP广播。 缺点:UDP广播信号不稳定,无法确定每一台机器能接收到信号
思路2:将一台主机作为服务器,使用TCP协议用此服务器转发消息 缺点:需要另外开发服务端,且其他端必须配置IP,灵活性差。
本文讲述的是第三个思路
思路3:开启程序后先设法发现其他终端,每个终端开启一个TCP服务socket,需要发广播的机器开启多个TCP客户端连接其他终端的TCP服务端稳定通信,至于如何使所有终端能相互发现 本文使用的是用UDP广播信号暴露自己,另外还可使用局域网遍历端口等方式。
代码:
发广播暴露自己:
Thread BroadcastTh;
/// <summary>
/// 发起广播使其他终端能检测到
/// </summary>
public void StartBroadCast()
{
try
{
if (BroadcastTh != null)
{
BroadcastTh.Abort();
}
BroadcastTh = new Thread(() =>
{
int i = ;
while (i < )
{
i++;
Thread.Sleep();
SendBroadcast("ConnectMe", );
}
});
BroadcastTh.IsBackground = true;
BroadcastTh.Start();
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
} }
这边是每隔500毫秒连续发200次,也可以无限发送广播,本人有强迫症不喜欢 while(true),况且如果开启的机器太多机器发送的广播量太多,相互监听的就越多,影响通信流量。
public void SendBroadcast(string msg, int port)
{
try
{
Socket recieveSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, port);
byte[] data = Encoding.UTF8.GetBytes(msg);
recieveSock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, );
recieveSock.SendTo(data, iep);
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
} }
接收广播信号,将其他终端地址添加到本地列表
Socket BroadcastRecievesocket;
/// <summary>
/// 监听广播信号
/// </summary>
public void ReceiveBroadcast()
{
Thread receiveThread = new Thread(() =>
{
try
{
BroadcastRecievesocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, );
EndPoint ep = (EndPoint)iep;
BroadcastRecievesocket.Bind(iep);
while (true)
{
try
{
byte[] buffer = new byte[];
BroadcastRecievesocket.ReceiveFrom(buffer, ref ep);
string msg = Encoding.UTF8.GetString(buffer);
string endaddress = ep.ToString().Split(':')[];
if (msg.Replace("\0","") == "ConnectMe")
{
if (!SocketList.ContainsKey(endaddress) && endaddress != localhost)
{
StartBroadCast();
SocketList.Add(endaddress, null);
}
}
else if (msg.Replace("\0", "") == "Offline")
{
if (SocketList.ContainsKey(endaddress))
SocketList.Remove(endaddress);
}
// MessageBox.Show(time);
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
}
}
}
catch (Exception)
{
BroadcastRecievesocket.Dispose();
ReceiveBroadcast();
}
})
{
IsBackground = true
};
receiveThread.Start();
}
开启tcp服务端
#region TCP服务端
Socket socketWatch;
/// <summary>
/// 启动TCP服务端socket
/// </summary>
private void StartTCPServer()
{
try
{
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//点击开始监听时 在服务端创建一个负责监听IP和端口号的Socket
IPAddress ip = IPAddress.Any; //创建对象端口
IPEndPoint point = new IPEndPoint(ip, );
socketWatch.Bind(point);//绑定端口号
socketWatch.Listen();//设置监听
Thread thread = new Thread(Listen);
thread.IsBackground = true;
thread.Start(socketWatch);
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
}
}
private void Listen(object o)
{
try
{
Socket socketWatch = o as Socket;
while (true)
{
Socket socketSend = socketWatch.Accept();//等待接收客户端连接
Thread r_thread = new Thread(Received);
r_thread.IsBackground = true;
r_thread.Start(socketSend);
}
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
}
}
/// <summary>
/// 服务器端不停的接收客户端发来的消息
/// </summary>
/// <param name="o"></param>
void Received(object o)
{
try
{
Socket socketSend = o as Socket;
while (true)
{
//客户端连接服务器成功后,服务器接收客户端发送的消息
byte[] buffer = new byte[];
//实际接收到的有效字节数
int len = socketSend.Receive(buffer);
if (len == )
{
break;
}
string str = Encoding.UTF8.GetString(buffer, , len);
HandleTime(str);
}
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
}
}
#endregion
发消息时开启多个TCP客户端连接列表中IP地址对应的服务端
Thread broadcast = new Thread(() =>
{
string[] keyStr = SocketList.Keys.ToArray();
for (int i = keyStr.Length - ; i >= ; i--)
{
try
{
Socket socketitem;
if (SocketList[keyStr[i]] != null)
{
socketitem = SocketList[keyStr[i]];
}
else
{
socketitem = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ;
IPAddress ip = IPAddress.Parse(keyStr[i]);
IPEndPoint point = new IPEndPoint(ip, );
socketitem.Connect(point);
}
DateTime dateTime = DateTime.Now;
string minisec = (Convert.ToDecimal(dateTime.Millisecond) / ).ToString("0.0000");
socketitem.Send(Encoding.UTF8.GetBytes(dateTime.ToLongTimeString() + minisec.Substring(, minisec.Length - )));
}
catch (Exception ex)
{
SimpleLog.WriteLog(ex.ToString());
SocketList.Remove(keyStr[i]);
}
}
});
broadcast.IsBackground = true;
broadcast.Start();
以上代码是部分代码。仅供参考
总结:然并卵
.net 使用TCP模拟UDP广播通信加强广播通信的稳定性的更多相关文章
- FTP和TCP、UDP
应用:TFTP客户端 1. TFTP协议介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议) 是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文 ...
- 基于TCP与UDP协议的socket通信
基于TCP与UDP协议的socket通信 C/S架构与初识socket 在开始socket介绍之前,得先知道一个Client端/服务端架构,也就是 C/S 架构,互联网中处处充满了 C/S 架构(Cl ...
- 以QQ举例 说明计算机网络中的一些概念区别(TCP与UDP,广播与单播)
QQ 中的 广播与单播 今天简单地学习了一下 广播和多播(组播) 的知识.关于 单播和多播 的概念,可以用 QQ 中的一些例子来解释. 单播,就像 两个人聊QQ 一样,信息的接收和传递只在两个节点之间 ...
- 计算机网络通信、线程、tcp、udp通信及信号量等读书笔记
一.计算机网络 1.什么是计算机网络:把分布在不同地理位置的计算机与专门的网络设备用通信线路互相连成一个规模大.功能强的系统,从而使众多计算机可以方便地互相传递信息.共享软件.硬件.数据信息等.简单来 ...
- TCP、UDP、Socket 通信(原)
说明:本随笔主要演示自己给自己发送消息例子,分别使用了TCP协议.UDP协议以及socket套接字通信.使用socket套接字了模拟TCP.UDP通信实现原理.其中有些源码都来自<C#高级编程 ...
- 实现TCP、UDP相互通信及应用
实验名称 Socket编程综合实验(1) 一.实验目的: 1.理解进程通信的原理及通信过程 2.掌握基于TCP和UDP的工作原理 3.掌握基本的Socket网络编程原理及方法 二.实验内容 1.掌握 ...
- 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP
[源码下载] 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP 作者:webabcd 介绍重新想象 Windows 8 Store ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.2.3 正式宣布
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件.广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.2.2 正式公布
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...
随机推荐
- 使用Putty + Xming 远程登录Linux显示图形化界面
一般我们远程登录linux 服务器,都是使用非加密的 telnet 或者加密的 ssh.这些登录方式有一个特点:只能登录字符界面,不能运行那些带有GUI界面的程序. 有时候为了学习或者工作的需要,我们 ...
- Docker学习之搭建nginx环境
前言 很久没写随笔了,今天我们来学习一下如何在docker搭建nginx环境吧! 一:下载镜像,使用docker pull拉取最新的nginx镜像 命令:docker pull nginx 查看镜像: ...
- 普通企业的规划类项目中,OptaPlanner更适合作为APS的规划优化引擎
在企业的规划.优化场景中,均需要开发规划类的项目,实现从从种可能方案中找出相对最优方案.如排班.生产计划(包括高层次的供应链优化,到细粒度的车间甚至机台作业指令).车辆调度等.因为这类场景需要解决的问 ...
- VBScript - 弹出“文件选择对话框”方法大全!
本文记录,VBScript 中,各种打开 "文件选择对话框" 的方法. 实现方法-1 (mshta.exe): 首先,我们要实现的就是,弹出上面的这个"文件选择对话框&q ...
- Wireshark的使用(抓包、过滤器)
Wireshark的使用(抓包.过滤器) 听语音 分步阅读 Wireshark这个转包工具的简单实用 工具/原料 Wireshark软件包 方法/步骤 Wireshark是世界上最流行的网络分析工具. ...
- git 从另一个分支融合部分文件
# git checkout master # git checkout anotherBranch -- abc ./etc # git commit -m "merge some fil ...
- Hadoop安装教程_伪分布式
文章更新于:2020-04-09 注1:hadoop 的安装及单机配置参见:Hadoop安装教程_单机(含Java.ssh安装配置) 注2:hadoop 的完全分布式配置参见:Hadoop安装教程_分 ...
- MySQL入门,第一部分,全局管理命令
1.连接数据库命令 mysql -h localhost -u root -p 回车后输入密码即可连接到数据库 2.显示当前mysql管理系统中的所有数据库 SHOW DATABASES; 3.显示当 ...
- Linux网络安全篇,认识防火墙(二),Netfilter
一.概述 因为iptables软件利用的是数据包的过滤的机制.所以它会分析数据包的报头数据.根据报头数据与定义的规则来决定该数据是否可以放行.若数据包内容与规则内容相同则放行,否则继续与下一条规则进行 ...
- jvm入门及理解(一)——简介与体系架构
最近,在学习java虚拟机的内容中,在此总结和记录下学到的. 一.JVM在计算机中的位置 在我们初学java时,便知道java源文件文件会先通过Java编译器编译成字节码文件,这个过程是java编译过 ...