三沣开发知识 购物 网址 游戏 小说 歌词 地图 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 租车 短信 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题
autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml
html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> C# -> 【光学相机】关于网络通信的方法及函数 -> 正文阅读
 

[C#]【光学相机】关于网络通信的方法及函数

【光学相机】关于网络通信的方法及函数 一.TcpClient与TcpServe。
首先我们需要知道服务器的IP地址,在服务器端建立监听,当监听到客户端的连接请求后,连接到客户端。
而客户端则需要连接到指定的IP服务器地址,建立网络流,则可以实现通信。

接下来给出一个服务器端与客户端的实例:
服务器端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace fuwuqi
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                IPAddress Ip = IPAddress.Parse("127.0.0.1");
                //IPAddress提供网际协议地址的类,Parse将IP地址字符串转换为IPAddress的实例   
                TcpListener TcpList = new TcpListener(Ip, 8888);
                //TcpListener网络侦听类,从TCP网络客户端侦听连接,TcpListener (参数1,参数2),参数1表示本地IP地址,参数2表示用来侦听传入的端口连接   
                TcpList.Start();
                //启动对挂起连接数的传入链接请求的侦听   
                Console.WriteLine("Server start!");
                Console.WriteLine("Ip address:" +TcpList.LocalEndpoint);
                //LocalEndpoint获取服务端(即本地)地址与端口等信息   
                Console.WriteLine("Wait");
                Socket Soc = TcpList.AcceptSocket();//相当于启动客户端后,Socket被挂起
                //AcceptSocket表示接受挂起的连接请求,Socket为套接字接口的类   
                Console.WriteLine("Received Connection:" + Soc.RemoteEndPoint);
                //RemoteEndPoint获取客户端地址与端口等信息   
                byte[] b = new byte[100];
                int k = Soc.Receive(b);
                //Soc.Receive(b)从socket接收数据,将数据存入接收缓冲区列表中,k的值为该数据的长度   
                Console.WriteLine("Received data from client:");
                for (int i = 0; i < k; i++)
                    Console.Write(Convert.ToChar(b[i]));
                //Convert.ToChar(b[i])将数组b转换基本数据类型为char的类型并输出   
                ASCIIEncoding AS = new ASCIIEncoding();
                //ASCIIEncoding表示Unicode字符的ASCII字符编码类   
                Soc.Send(AS.GetBytes("Received data!"));
                //Soc.Send向客户端发送数据,AS.GetBytes()获得括号中字符串的bytes值   
                Soc.Close();
                //关闭连接并释放所有关联的资源   
                TcpList.Stop();
                //关闭侦听   
                Console.ReadLine();
                //等待输入,起到暂停的作用   
            }
            catch (Exception e)
            {
                Console.WriteLine("Error!" + e.StackTrace);
                //获取当前异常发生时调用堆栈上的帧的字符串   
            }
        }
    }
}

此时服务器端应用的是Socket类发送数据流,Socket类用于客户端和服务器都可,其发送机制是以一种包的形式发送,在做项目时,发现Socket接收到的数据包与发送到的数据包长度不一定吻合,有阻塞,所以使用Socket数据包发送时,接收和发送的数据组要指定长度,太长也会丢数。
客户端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net.Sockets;
namespace kehuduan
{
    class Program
    {
        
            static void Main(string[] args)  
        {
                try
                {
                    TcpClient TcpClient = new TcpClient();
                    //TcpClient为TCP网络服务提供客户端连接的类   
                    TcpClient.Connect("127.0.0.1", 8888);
                    //Connect方法使用指定的IP地址和端口号将客户端连接到远程TCP主机   
                    Console.WriteLine("Connect Complete");

                    Console.WriteLine("Input string:");
                    String str = Console.ReadLine();
                    //定义字符串str变量,保存输入的字符   
                    Stream stm = TcpClient.GetStream();
                    //定义数据流,用于发送和接收数据   
                    ASCIIEncoding AS = new ASCIIEncoding();
                    byte[] b = AS.GetBytes(str);
                    //将字符串转换为byte类型   
                    stm.Write(b, 0, b.Length);
                    //Write(参数1,参数2,参数3)表示向服务端发送字符串,参数1指将此数组复制到当前流,参数2指从零开始的字节偏移量,参数3指要写入当前流的字节数(即字符串长度)   
                    Console.WriteLine("Send Complete");
                    byte[] bb = new byte[100];
                    int k = stm.Read(bb, 0, 100);
                    //stm.Read在当前流中读入服务端发来的响应信息,其参数与Write方法参数一致,k值为读入字符串的长度   
                    for (int i = 0; i < k; i++)
                        Console.Write(Convert.ToChar(bb[i]));
                    TcpClient.Close();
                    //释放TcpClient实例,并不关闭基础连接   
                    Console.ReadLine();
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error!" + e.StackTrace);
                }
            }
        }
    }

上面展示了客户端与服务器端的简单通信。作为例子程序学习,接下来对自己做的项目中连接摄像头服务器做一个记录。
首先,把摄像头作为服务器端,定义客户端:
   TcpClient client = new TcpClient("IP",8080);
获取网络流:
  NetworkStream networkstream = client.GetStream();//获取网络流
此时可以建立与服务器端的网络流连接,如果需要从网络流中读取数据或者写入数据,使用了BinaryReader/BinaryWriter或者StreamReader/StreamWriter,实例化后,就可实现对流的读写
BinaryReaderbr = new BinaryReader(networkstream);
BinaryWriter bw = new BinaryWriter(networkstream);
我对这两个的理解是StreamReder读取函数ReadToEnd,ReadLine等,读取出来是字符串类型。而BinaryReader可以按字节读取。根据需求选取。
(笔记StreamReader的方法: sr.BaseStream.Seek(0, SeekOrigin.Begin);//从流中当前开始的位置(SeekOrigin.begin)偏移0位读取)
如果需要对服务器发送数据直接写入流,使用Write等函数就可以了。
这里对自己找的资料也做一个总结。
MemoryStream类:
Memmory类相当于一个缓存流,首先需要对这个流开辟一个空间,然后将数据放入流中对其进行操作。该流的优势在于可以将数据先放入流中,然后使用指针对流中的任一个字节进行操作。
学习例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //属性测试
            MemoryStream ms = new MemoryStream();
            Console.WriteLine(ms.CanRead);      //True  内存流可读
            Console.WriteLine(ms.CanSeek);      //True  内存流支持查找,指针移来移去的查找
            Console.WriteLine(ms.CanTimeout);   //False 内存流不支持超时
            Console.WriteLine(ms.CanWrite);     //True  内存流可写

            Console.WriteLine(ms.Capacity);     //0     分配给该流的字节数
            byte[] bytes = Encoding.UTF8.GetBytes("abcdedcba");//字符转为ASCII
            ms.Write(bytes, 0, bytes.Length);   //已将一段文本写入内存
            int l = bytes.Length;
            Console.WriteLine(ms.Capacity);     //256   再次读取为文本流分配的字节数已经变成了256,看来内存流是根据需要的多少来分配的
            Console.WriteLine(ms.Length);       //9    这个是流长度,通常与英文的字符数一样,真正占用的字节数。

            Console.WriteLine(ms.Position);     //9    流当前的位置,该属性可读可设置

            //Console.WriteLine(ms.ReadTimeout);    由于流不支持超时,此属性如果读取或者设置的话会报错
            //Console.WriteLine(ms.WriteTimeout);   由于流不支持超时,此属性如果读取或者设置的话会报错

            //方法测试
            
            byte[] byte1 = ms.GetBuffer();          //返回无符号字节数组 差点被忽悠了,无符号字节数组 其实就是byte(0~255),有符号字节sbyte(-128~127)
            string str1 = Encoding.UTF8.GetString(byte1);
            Console.WriteLine(str1);    //输出    abcdedcba
            long p = ms.Position;//指针当前位置
            ms.Position = 0;
            ms.Seek(0, SeekOrigin.Current);    //设置当前流正在读取的位置 为开始位置即从0开始
            //从内存中读取一个字节
            int i = ms.ReadByte();
            Console.WriteLine(i);                   //输出99
            byte[] bytes3 = ms.ToArray();
            foreach (byte b in bytes3)
            {
                Console.Write(b + "-");//用于对比   输出 97-98-99-100-101-100-99-98-97-   可以看到    0,1,2第二位刚好是99
            }

            MemoryStream ms2 = new MemoryStream();
            byte[] bytes6 = Encoding.UTF8.GetBytes("abcde");
            ms2.Write(bytes6, 0, bytes6.Length);
            Console.WriteLine(ms2.Position);    //输出5 写完之后流的位置就到了最后,因此想用read读取必须加下面这一行代码。 

            //ms2.Seek(0, SeekOrigin.Begin);    //想要用Read方法读取完整的流,必须设置当前位置,Read是从Position的位置开始读。
            ms2.Position = 0;                   //Read是从当前位置开始读,这行代码和上面一行意义一样。
            byte[] byteArray = new byte[5] { 0, 0,0, 0, 0 }; //数组附初值全部是0
            ms2.Read(byteArray, 2, 1);   //读取一个字节,byteArray的第一个元素中,(注意从0开始)读取数据流里第二个位子开始读取一个
            Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnann
            ms2.Read(byteArray, 2, 2);
            Console.WriteLine(Encoding.UTF8.GetString(byteArray)); //nnabn    //当超出接收数组总长度的时候,后面的元素会被移开


            //设置当前流的长度
            Console.WriteLine(ms.Length);   //输出9   当前流的长度是9
            ms.SetLength(20);
            Console.WriteLine(ms.Length);   //输出20
            foreach (byte b in ms.ToArray())    //将流的内容也就是内存中的内容转换字节数组
            {
                Console.Write(b + "-");     //输出 97-98-99-100-101-100-99-98-97-0-0-0-0-0-0-0-0-0 由于设置了长度,因此空的自动补0
            }
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));   //输出    abcdedcba   虽然长度变长了,但是没影响读取数据

            MemoryStream ms1 = new MemoryStream();
            byte[] bytes4 = ms1.ToArray();
            Console.WriteLine("此内存流并没有写入数据(Write)" + Encoding.UTF8.GetString(bytes4));//输出    此内存流并没有写入数据(Write)  因为内存为空


            //下面来一个指定位置的写入
            MemoryStream ms3 = new MemoryStream();
            byte[] bytesArr = Encoding.ASCII.GetBytes("abcdefg");
            ms3.Write(bytesArr, 0, bytesArr.Length);
            ms3.Position = 2;
            ms3.WriteByte(97);  //97代表的是a   这段代码的意思是,将原先第二个的c替换为a
            string str = Encoding.ASCII.GetString(ms3.ToArray());
            Console.WriteLine(str); //输出 abacdefg

            byte[] byteArr1 = Encoding.ASCII.GetBytes("kk");
            ms3.Position = 4;
            ms3.Write(byteArr1, 0, byteArr1.Length);
            Console.WriteLine(Encoding.UTF8.GetString(ms3.ToArray()));  //abadkkg   //从第4位替换掉了两个字节为KK

            Console.ReadKey();
        }
    }
}

  C# 最新文章
字符串阵列分别输出元素的索引,原值和长度
格式化你的字符串
C#宣告一个变量
C#中级
拆分一个字符串并把每个字符单独输出
通过手机号定位归属地
C# 在引用插件中 出现的问题| Csharp cite
汽车租赁系统
C#中结构体定义并转换字节数组
小知识(五):抽象类&接口
上一篇文章      下一篇文章      查看所有文章
加:2017-12-07 23:26:04  更:2017-12-07 23:26:25 
 
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年4日历
2018-4-24 1:24:24
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库