应用场景:当每一台终端开启程序后发出消息,其他终端必须收到消息然后处理

思路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广播通信加强广播通信的稳定性的更多相关文章

  1. FTP和TCP、UDP

    应用:TFTP客户端 1. TFTP协议介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议) 是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文 ...

  2. 基于TCP与UDP协议的socket通信

    基于TCP与UDP协议的socket通信 C/S架构与初识socket 在开始socket介绍之前,得先知道一个Client端/服务端架构,也就是 C/S 架构,互联网中处处充满了 C/S 架构(Cl ...

  3. 以QQ举例 说明计算机网络中的一些概念区别(TCP与UDP,广播与单播)

    QQ 中的 广播与单播 今天简单地学习了一下 广播和多播(组播) 的知识.关于 单播和多播 的概念,可以用 QQ 中的一些例子来解释. 单播,就像 两个人聊QQ 一样,信息的接收和传递只在两个节点之间 ...

  4. 计算机网络通信、线程、tcp、udp通信及信号量等读书笔记

    一.计算机网络 1.什么是计算机网络:把分布在不同地理位置的计算机与专门的网络设备用通信线路互相连成一个规模大.功能强的系统,从而使众多计算机可以方便地互相传递信息.共享软件.硬件.数据信息等.简单来 ...

  5. TCP、UDP、Socket 通信(原)

    说明:本随笔主要演示自己给自己发送消息例子,分别使用了TCP协议.UDP协议以及socket套接字通信.使用socket套接字了模拟TCP.UDP通信实现原理.其中有些源码都来自<C#高级编程 ...

  6. 实现TCP、UDP相互通信及应用

    实验名称  Socket编程综合实验(1) 一.实验目的: 1.理解进程通信的原理及通信过程 2.掌握基于TCP和UDP的工作原理 3.掌握基本的Socket网络编程原理及方法 二.实验内容 1.掌握 ...

  7. 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP

    [源码下载] 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP 作者:webabcd 介绍重新想象 Windows 8 Store ...

  8. 高性能 TCP &amp; UDP 通信框架 HP-Socket v3.2.3 正式宣布

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件.广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...

  9. 高性能 TCP &amp; UDP 通信框架 HP-Socket v3.2.2 正式公布

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...

随机推荐

  1. JS去除字符串内的空白字符方法

    有时我们需要对用户的输入进行一些处理,比如用户输入的密码或者用户名我们就需要去除前后空格,下面写一个去除空白字符的方法 function trim(string = '') { return stri ...

  2. new FileReader()

    一.调用FileReader对象的方法 方法名 参数 描述abort none 中断读取readAsBinaryString file 将文件读取为二进制码readAsDataURL file 将文件 ...

  3. 【网络安全】——客户端安全(浏览器安全、XSS、CSRF、Clickjacking)

    ​ 近在学习网络安全相关的知识,于是先从业内一本系统讲Web安全的书<白帽子讲Web安全>系统学习Web安全的相关知识.在此整理书中的知识层次,不求详尽,只求自己对整个Web安全梗概有所了 ...

  4. 剑指offer—单链表反转的三种实现方法

    单链表的反转可以用递归.非递归和栈的方法实现 链表节点定义: struct ListNode{ int val; Node* next; ListNode(int x):val(x),next(nul ...

  5. LeetCode 题解 | 面试题57 - II. 和为s的连续正数序列

    题目描述 面试题57 - II. 和为s的连续正数序列 难度简单37收藏分享切换为英文关注反馈 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数). 序列内 ...

  6. android学习相关intent和fragment的先关知识点

    对于使用intent,主要是用来进行活动之间的跳转,然后就是通过intent向下一个活动传递数据,还有就是想上一个活动传递数据. 实例: 先添加按钮的点击事件,当点击按钮时进行事件的触发,主要代码是 ...

  7. Linux基础篇,正则表达式

    一.正则表达式特殊符号: 二.grep的用法 grep [-A|B|a|c|i|n|v] [--color=auto] '搜索字串' filename -A ===> after缩写,后面接数字 ...

  8. String 对象-->substr() 方法

    1.定义和用法 substr() 方法可在字符串中抽取从 开始 下标开始的指定数目的字符. 语法: string.substr(start,length) 参数: start:提取开始下标 lengt ...

  9. lr组织架构模式

    基本模式:默认目录由三部分组成 Vuser_int Action,…… Vuser_end 执行时会按照这三个顺序执行(Action部分是可以循环的,也可多个action) 1.lr12录制前可以设置 ...

  10. editplus 怎么替换为换行

    到editplus 的搜索 菜单中,选择替换,记住 这边如果是简单的一些 通用字符 替换可以直接替换,如果是一些特殊的字符 那必须选择 替换框左下中间的 “正则表达式”,即把这个“正则表达式” 前边的 ...