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

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

最近有遇到过这样一个问题,将摄像头识别的行人,车辆实时显示在客户端中。有提供接口,会以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的死胡同里,怎么都出不来,白白浪费时间不说,把人也搞得很疲惫。这里多谢同事的指点,以后多像技术高手学习,毕竟阅历有时候真的就是硬实力。

原文地址:https://www.cnblogs.com/Sientuo/p/9733041.html

时间: 2024-08-10 11:28:32

UDP广播 与 TCP客户端 --服务端的相关文章

利用TCP 客户端---->服务端 传送文件到指定路径,并返回一个友好的回馈

首先盲写的一个传输文件的方法,但测试发现了一个非常不容易发现的问题,这里先说明一下. 错误的代码如下: 1 package com.TCP.java; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import j

java TCP客户端 服务端 互访

服务端: 1, 创建socket服务器服务,服务器端为了让客户端可以连接上,必须提供端口,监听一个端口 2,获取客户端对象,通过客户端的socket流和对应的客户端进行通信 3,获取客户端的socket流的读取流 4,读取数据并显示在服务器端 5,关闭资源 package cn.net.tcp; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.

TCP客户端 服务端详细代码

本文章转自http://www.myexception.cn/program/1912019.html TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数 对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三次握手,而这个连接的过程是由内核完成,不是这个函数完成的,这个函数的作用仅仅是通知 Linux 内核,让 Li

go语言实现 tcp客户端/服务端

/ server.go /package main import ("bufio""fmt""net""time") func main() {var tcpAddr *net.TCPAddr tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:9999") tcpListener, _ := net.ListenTCP("tcp

socket 网络编程快速入门(二)教你编写基于UDP/TCP的服务端多线程通信

在上一篇博文中,我们介绍了利用socket进行简单的UDP/TCP的服务端和客户端的通信. (一) 在基于UDP的程序中,你有没有想过,如果我的这台主机在通讯的时候要求既能够收到别的主机发来的数据,又能够自己向目的主机发出数据,该怎样实现?也就是说需要两个while循环同时进行.答案是使用多线程,一个线程用于接受数据,另一个线程用来发送数据.接下来我们介绍WinSock的多线程编程. 多线程的实现我们使用_beginthread()函数: uintptr_t _beginthread( void

TCP/IP网络编程之基于TCP的服务端/客户端(二)

回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服务端的I/O代码 echo_server.c --while ((str_len = read(clnt_sock, messag, 1024)) != 0) write(clnt_sock, messag, str_len);-- 接着,我们回顾客户端的代码 echo_client.c -- wr

Android版网络办公系统应用客户端+服务端

该项目源码是Android版网络办公系统应用客户端+服务端,也是一个简单的网上办公系统的Android客户端,项目有服务端和客户端部分的源码的,客户端开发环境eclipse  AVD版本 4.0服务器 phpStudy 2013集成环境 Apache+php5.3+ISAPI模式 phpStudy 2013集成环境绿色版下载http://www.phpstudy.net/phpstudy/phpStudy2013d.zip官网   http://www.phpstudy.net/ android

网易新闻应用源码完整版客户端+服务端源码

这个源码是从安卓教程网android分享过来的,看到这个项目比较不错,就转了.网易新闻应用源码完整版客户端+服务端源码,仿网易新闻,android端+服务器端1,为了加快访问速度,服务器端数据是写死了的,数据太多的就复制粘贴了,不是数据库查询的2,新闻图片下载代码注释掉了(网速给力的可以放开注释),显示的是默认图片 3.运行时记得改android端Constantvalues类里面的IP地址4,  UI结合使用的挺不错的等.<ignore_js_op>   <ignore_js_op&g

使用ranch tcp开发服务端

Ranch: 简单来说,Ranch就是一个tcp acceptor pool,用于高并发下的tcp连接建立与管理.可以设置并发链接最大数量,在不关闭socket连接的情况下可以动态升级连接池.Cowboy就是使用的ranch. https://github.com/ninenines/ranch 下面通过改造ranch自带的reverse example实现简易的服务端. game_server.app.src {application, game_server, [ {description,