UDP广播 与 TCP客户端 --服务端

摘要:
它将以Json数据的形式实时发布识别的对象。EventArgse){//创建TCP客户端对象TcpClienttcpClient=newTcpClient();if(networkStream.CanWrite){//通过tSend=Encoding.UTF8.GetBytes(textBox1。文本);

       随着倒计时的响声,自觉无心工作,只想为祖国庆生。

       最近有遇到过这样一个问题,将摄像头识别的行人,车辆实时显示在客户端中。有提供接口,会以Json的数据的形式将实时将识别的对象进行Post提交。所以我们这边先写一个web服务来持续接收数据,再将数据进行解析存入数据库。到这里为止,数据没有问题,都全部存入数据库中,这样还剩下一个实时刷新识别图片的问题。之前的处理方法是每隔5秒左右去读取数据库最新消息,用Timer计时器来解决,这样的话确实能解决问题,但是感觉不是最好的方法,因为摄像头识别的对象有时效性,比如半夜几乎没人通过,这个时候后台还在去捞取最新数据进行判断就比较消耗资源。所以我先想到的是用 TCP方法来处理, web在解析图片的时候, 进行发送,winform客户端进行接收。貌似可以解决问题,先上代码

        private void button1_Click(object sender, EventArgs e)
        {
            //创建TCP客户端对象
            TcpClient tcpClient = new TcpClient();
            //添加目标(服务器)主机的IP、端口号
            tcpClient.Connect(IPAddress.Parse("172.16.0.217"), 8056);
            //网络流 数据的形式
            NetworkStream networkStream = tcpClient.GetStream();
            if (networkStream.CanWrite)
            {
                //待发送数据转Byte[]
                Byte[] bytSend = Encoding.UTF8.GetBytes(textBox1.Text);
                networkStream.Write(bytSend, 0, bytSend.Length);
            }
            else
            {
                MessageBox.Show("无法写入数据流");

                networkStream.Close();
                tcpClient.Close();

                return;
            }
            //流创建完需要及时关闭
            networkStream.Close();
            tcpClient.Close();

        }  

这里是TCP的客户端,指定了接收端的IP和端口号,以及发送的数据流,同样在服务端选择接受这些流数据。服务端要持续接收数据,就必须开启一个线程进行监听

        private void Form1_Load(object sender, EventArgs e)  
        {
            //初始化加载数据
            Thread thread = new Thread(new ThreadStart(Listen));
            thread.Start();
        }


        //线程内向文本框txtRecvMssg中添加字符串及委托
        private delegate void serverRecDeg(string s);
        private void ReceiveMsg(string mes)
        {
            textBox1.Text = "Time:" + DateTime.Now.ToLongTimeString() + "Data:" + mes;
        }

        //监听数据
        private void Listen()
        {
            //socket 对象
            Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
            sock.Bind(new IPEndPoint(IPAddress.Any, 8056));

            //不断监听端口
            while (true)
            {
                sock.Listen(0);
                Socket socket = sock.Accept();
                NetworkStream ntwStream = new NetworkStream(socket);
                StreamReader strmReader = new StreamReader(ntwStream);
                //winform UI控件赋值,如果有线程,则需要用Invoke 来赋值,则否报错
                Invoke(new serverRecDeg(ReceiveMsg),new object[] { strmReader.ReadToEnd() });
                socket.Close();
            }            
        }

以上是TCP客户端发送数据,服务端持续接收。刚开始自认没问题,但是后来一想确实不可行。我web服务端是发送数据的,客户端是用来接收数据。TCP是客户端指定服务端唯一的IP 和端口号进行数据的传输,这里明显就冲突了,如果在Web服务端用TCP发送数据,

就只能有一个客户端进行接收,需求是winform最后要部署到不同机器上,这种思路肯定不行。思来想去,最后在同事的指点下,想到了广播这一思路。在web服务端每次解析到图片的时候,发一个广播,然后隐藏在局域网内的各个客户端就可以进行收听,解析后将图片 

        //定义对象
        private static Socket sock;
        private static IPEndPoint ipendPoint;
        private static byte[] data;

        //发送广播
        public static void UdpSend(byte[] bytes1)
        {
            //sock 对象,指定UDP协议
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            ipendPoint = new IPEndPoint(IPAddress.Broadcast, 9050);
            //赋值
            data = bytes1;
            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            //发送
            sock.SendTo(data, ipendPoint);

        }

这里使用的是UDP广播,代码量很少,发送端已经完成,剩下的就是客户端持续接收广播

        public void Receive()
        {
            try
            {
                //Scok 对象,设置UDP协议
                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                //超时时间
                sock.ReceiveTimeout = 4000;
                //广播的端口号指定
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
                sock.Bind(iep);
                EndPoint ep = (EndPoint)iep;
                //数据接收(指定异步接收的方法)
                sock.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), sock);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //指定单次接收图片流缓冲区的大小
        static byte[] buffer = new byte[102400];

        //异步接收
        public void ReceiveMessage(IAsyncResult ar)
        {
            try
            {
                var socket = ar.AsyncState as Socket;              
                var length = socket.EndReceive(ar);
                //读取出来消息内容
                //var message = Encoding.UTF8.GetString(buffer, 0, length);               
                //前三个长度为对象类型 车辆/行人 ,后面识别图片
                //解析图片类型
                string objType = System.Text.Encoding.Default.GetString(buffer.Skip(0).Take(3).ToArray());
                //解析图片
                Image img = convertImg(buffer.Skip(3).ToArray());                              
                //显示消息
                this.Invoke(new Action(() => { SetPicBoxImg(objType, img); }));                                              
                //接收下一个消息(递归)
                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

这些做完,剩下的就是将接收广播的方法写入到后台线程中,在窗体运行的时候启动即可

 Thread td = new Thread(new ThreadStart(Receive));
 td.IsBackground = true;
 td.Start();

好了,事情到这里基本就结束了,可以看出来,代码量很少,却能解决实时刷新的需求。以后遇到事情一定要思路明确,不然一开始钻进TCP的死胡同里,怎么都出不来,白白浪费时间不说,把人也搞得很疲惫。这里多谢同事的指点,以后多像技术高手学习,毕竟阅历有时候真的就是硬实力。

免责声明:文章转载自《UDP广播 与 TCP客户端 --服务端》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis 的安装与使用Linux 环境下 node 以及 jit 的简单环境配置说明下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JS点击img图片放大再次点击缩小JS实现 简单实用Ctrl+C+V就可以用

业务需要,从后台获取的图片列表,用img标签展示,用户需要查看大图。记录下来以便学习和参考.示例图如下: 放大之前: 放大之后: 点击后放大(由于图片高度超出了页面,需要通过overflow:auto;设置滚动条,点击放大图片回到列表界面) 附代码(js实现): 1、获取所有img标签,添加展开功能,该方法在图片列表加载完成以后执行: 1...

LRU缓存及其实现

缓存是我们日常开发中来提高性能最直接的方式,经常会听到有人说:性能不行?是因为你没加缓存!常见的缓存有外部缓存服务以及程序内部缓存,外部缓存服务包括:Redis、Memcached等,内部缓存就是我们可以在程序内使用类似HashMap这种方式来建立缓存,另外比如Web中常见的cdn静态资源缓存等也属于缓存,以及我们计算机中的CPU缓存,文件系统缓存等都不约...

MQTT协议的简单介绍和服务器的安装

转:http://blog.csdn.net/djun100/article/details/25752491   最近公司做的项目中有用到消息推送,经过多方面的筛选之后确定了使用MQTT协议,相对于XMPP,MQTT更加轻量级,并且占用用户很少的带宽。 MQTT是IBM推出的一种针对移动终端设备的基于TCP/IP的发布/预订协议,可以连接大量的远程传感器...

kaggle kernel使用指南

有几个要注意的地方: 1、可以选择CPU或GPU,但是机器学习模型一般的CPU就够了,最近(2019.04)使用GPU的话一小时后总是会断开连接,这时候要跑久一点的cell就凉了。 2、导入文件:支持自行导入,如果是kaggle上的数据也可以直接从官方比赛数据中选择,导入到右侧的workspace中后,在代码中要导入csv文件,其路径就是点击workspa...

spark之单词统计

spark之单词统计 1.Java语言开发单词统计 package com.wordCountdemo2; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; i...

【深度学习系列】PaddlePaddle可视化之VisualDL

  上篇文章我们讲了如何对模型进行可视化,用的keras手动绘图输出CNN训练的中途结果,本篇文章将讲述如何用PaddlePaddle新开源的VisualDL来进行可视化。在讲VisualDL之前,我们先了解一下常用的Tensorflow的可视化工具---Tensorboard。 Tensorflow的可视化   Tensorboard是Tensorfl...