.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#. ...
随机推荐
- HDU-1421-搬寝室(01背包改编版)
搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太 ...
- 1057 Stack (30分)(树状数组+二分)
Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...
- composer换源,composer切换国内源
首先要分清楚是局部换源还是全局换源 1.局部换源(仅对当前项目有效) 在当前项目下的composer.json中添加 { "repositories": [ { "typ ...
- LVS 集群与存储《路由转发》
LVS 集群与存储<路由转发> 集群简介 u 什么是集群 • 一组通过高 ...
- 深入理解智能指针之shared_ptr(一)
本文基于C++标准库源码分析shared_ptr,旨在搞清楚shared_ptr是什么,线程安全性等,目标能够安全的使用智能指针. (一)shared_ptr是一个类. 首先可以确定的是shared_ ...
- idea运行gradle项目报错,找不到符号符号,方向xxxx类未知
报错: 解决:把build和run设置为idea
- coding++:都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事
都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事 就用下面这段代码在jdk的三个版本运行看了下效果: import java.lang.reflect.Fiel ...
- git撤销远程commit
git reset --hard [commit_id] git push origin HEAD --force
- Xray安装与使用
0×00 Xray简介 xray是从长亭洞鉴核心引擎中提取出的社区版漏洞扫描神器,支持主动.被动多种扫描方式,自备盲打平台.可以灵活定义 POC,功能丰富,调用简单,支持 Windows / macO ...
- 第十三节:telnetlib、redis、threading模块
telnetlib模块案例: import telnetlib,re class TelnetInfo(): def telnetdo(self, host, port, command): tn = ...