两个平台互相通信,对方发送数据过来,我方接收数据,对数据进行处理后发送结果给对方,对方进行相应的操作。

  首页,我方开启服务监听:

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
socket.Bind(endPoint);
socket.Listen();
Socket clientReqSocket = socket.Accept();
byte[] arrMsg = new byte[ * ];
int arrLen = clientReqSocket.Receive(arrMsg);

  提取实际有效数据:

            byte[] arrNew = new byte[arrLen];
Buffer.BlockCopy(arrMsg, , arrNew, , arrLen);

  在对接收到的数据arrNew进行业务处理之后,将结果arrResult返回给对方,最后关闭连接:

            clientReqSocket.Send(arrResult);
clientReqSocket.Close();
       socket.Close();

  对上面代码进行讲解:首先,socket.Accept();这个方法,服务会一直停留在这个方法上面,等待客户端的连接,一有客户端连接上来,才会继续执行下面的代码。如果没有客户端来连接服务,程序将会一直停留在这个地方,会出现“假死”的现象。其次,上面的代码示例只能处理一个客户端的连接请求,请求处理完成后,就会关闭连接。服务端应该是一个永不会停止的程序,能够一直监听客户端的请求,并对其进行处理和回馈。

  所以对上面的问题进行说明,首先使用线程,开启服务后,服务端处理监听状态,当有客户端连接请求上来后,为该客户端连接新创建一个线程,专门来处理该客户端的请求操作。当有多个客户端连接上来后,服务会为每个客户端都新创建线程来处理。这样服务可以继续监听其他客户端的连接请求,一边又可以对已连接上来的客户端进行响应处理。其次,要服务队能够永远的监听客户端的连接请求,就必须让服务端在处理完一个客户端的连接请求后,能够继续调用socket.Accept()来监听连接请求,这里使用while(true){}无限循环来实现。

        bool isListener = true;

        /// <summary>
/// 监听远程数据
/// </summary>
void startListen()
{
while (isListener)
{
try
{
Socket clientReqSocket = socket.Accept();
byte[] arrMsg = new byte[ * ];
int arrLen = clientReqSocket.Receive(arrMsg); byte[] arrNew = new byte[arrLen];
Buffer.BlockCopy(arrMsg, , arrNew, , arrLen);      //进行业务处理后(此处省略部分代码),返回arrResult。
clientReqSocket.Send(arrResult);
clientReqSocket.Close();
}
catch (Exception ex)
{
isListener = false;
}
}
}

  由于本次需求上只有一个客户端,所以这次没有采用多线程的方式。只是在主线程上,新建一条线程专门用来监听和处理客户端的请求操作,这样主线程还可以继续执行它的任务,程序也不会出现“假死”的状态。

  当然,对于客户端发送过来的数据,服务端要能进行识别判断,提取有效数据。所以在本次双方通信过程中,对数据的格式进行了约定,只有遵循了格式的数据才会进行处理解析和响应。接口协议定义如下表所示(数据协议XML结构定义省略):

通讯数据包结构定义如表下:
包头标记 总长 消息类型 XML流长度 XML格式数据 包尾标记
4B 4B 1B 4B   2B
数据包内各项目定义说明如下表:
序号 项目名称 取值 说明
1  包头 0xE1 0x2B 0xD3 0x78 取固定值
2 总长   4个字节(包括包头包尾的长度)
3 消息类型 0x21 或者 0x22 用于区别数据包的类型
4 XML流长度   XML格式数据的长度(4bytes)
5 XML格式数据   为所传递的XML报文
6 包尾 0xFF 0xFF 取固定值
数据包协议类型说明如下表:
消息号 说明 XML格式
0x21 表示客户端向服务端发送数据 XMLInfoSed
0x22 表示服务端向客户端发送数据 XMLInfoReq

  定义好通信协议之后,Socket通信就需要遵循这个协议,服务端和客户端都只接收该遵循该协议的报文和发送该格式的报文。

        bool isListener = true;

        /// <summary>
/// 监听远程数据
/// </summary>
void startListen()
{
while (isListener)
{
try
{
Socket clientReqSocket = socket.Accept();
byte[] arrMsg = new byte[ * ];
int arrLen = clientReqSocket.Receive(arrMsg); if (arrLen != )
{
byte[] arrNew; if (arrMsg[] == 0x21)//接收数据
{
try
{
arrNew = new byte[arrLen];
//提取XML数据部分 数据包定义:头13字节 XML数据 尾2字节
Buffer.BlockCopy(arrMsg, , arrNew, , arrLen - );
                   string msg = Encoding.GetEncoding("GB2312").GetString(arrNew);
XmlDocument xmlDom = new XmlDocument();
//加载XML数据
xmlDom.LoadXml(msg);
//解析XML数据,将XML数据发送给后台系统进行业务逻辑处理(此处省略)
clientReqSocket.Close();
}
catch (Exception ex)
{
clientReqSocket.Close();
continue;//服务继续监听
}
} else if (arrMsg[] == 0x22)//接收发送数据
{
try
{
byte[] arrNew = new byte[];
//包头标记 固定值 (4B)
arrNew[] = 0xE1;
arrNew[] = 0x2B;
arrNew[] = 0xD3;
arrNew[] = 0x78;
//消息类型 0x22 表示为服务端向客户端发送数据 (1B)
arrNew[] = 0x22; byte[] xmlArr = new byte[arrLen];
Buffer.BlockCopy(arrMsg, , xmlArr, , arrLen); string msg = Encoding.GetEncoding("GB2312").GetString(xmlArr); string hexLength = String.Format("{0:X8}", msg.Length); //XML流长度 需要统计 (4B)
arrNew[] = Convert.ToByte(hexLength.Substring(, ), );
arrNew[] = Convert.ToByte(hexLength.Substring(, ), );
arrNew[] = Convert.ToByte(hexLength.Substring(, ), );
arrNew[] = Convert.ToByte(hexLength.Substring(, ), ); //包首部 + XML数据长度 + 包尾部
int dataLen = arrNew.Length + xmlArr.Length + ; string dataHexLen = String.Format("{0:X8}", dataLen);
//总长 (包括包头包尾长度) 需要统计 4(B)
arrNew[] = Convert.ToByte(dataHexLen.Substring(, ), );
arrNew[] = Convert.ToByte(dataHexLen.Substring(, ), );
arrNew[] = Convert.ToByte(dataHexLen.Substring(, ), );
arrNew[] = Convert.ToByte(dataHexLen.Substring(, ), ); byte[] newArr = new byte[dataLen];
Buffer.BlockCopy(arrNew, , newArr, , arrNew.Length);
Buffer.BlockCopy(arr, , newArr, arrNew.Length, arr.Length);
newArr[dataLen - ] = 0xFF;
newArr[dataLen - ] = 0xFF; //向客户端发送数据
Socket toclientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(txtCIP.Text.Trim());
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtCPort.Text.Trim()));
toclientSocket.Connect(endPoint);
toclientSocket.Send(newArr); clientReqSocket.Send(new byte[] { });//发送成功 toclientSocket.Close();
                clientReqSocket.Close();
}
catch (Exception ex)
{
clientReqSocket.Send(new byte[] { });//发送数据失败
clientReqSocket.Close();
continue;
}
}
}
}
catch (Exception ex)
{
isListener = false;
}
}
}

  在这里本服务成为一个类似中转站的机器,客户端向本服务发送数据,本服务接收数据,对数据进行解析,解析完成后将数据交给后台系统,后台系统对数据进行业务逻辑处理后,将结果数据发送给本服务,然后本服务将最后结果数据发送给客户端。原本不需要本服务中间这一环节,客户端和后台系统可以直接进行通信交互,但是因为业务要求,所以必须要有本服务这一中间环节。

  对上面代码进行说明:首页本服务要先判断接收到的数据为客户端发送来的数据,还是后台系统需要向客户端发送的数据。根据通信数据包结构定义,消息类型占1个字节,前面有包头4字节和总长4字节共8个字节,所以消息类型在第9个字节的位置。对接收到的数据arrMsg[8]第9个字节进行判断,如果arrMsg[8] = 0x22表示为客户端发送来的数据,客户端发送来的数据,本服务需要提取XML数据部分,然后对XML数据进行解析,将后台服务需要的数据发送给后台。

  Buffer.BlockCopy(arrMsg, 13, arrNew, 0, arrLen - 15);去除头13个字节和尾2个字节,提取XML数据部分。

  如果arrMsg[8] == 0x22表示后台系统要向客户端发送的数据,接收到后台系统发送过来的数据,首先要对数据进行封装,将数据组装成为约定好的XML结构(本服务接收到的数据就为XML数据),然后将该XML数据添加包头包尾,重新封装成为客户端能够识别的数据结构。将数据进行重新封装后发送给客户端,并且通知后台系统发送结果状态。

  在这里主要是想跟大家分享,在网络通信过程中,对于有通信接口格式定义的该如何进行交互。

Socket 两平台互相 通信 .NET的更多相关文章

  1. UE4 Socket多线程非阻塞通信

    转自:https://blog.csdn.net/lunweiwangxi3/article/details/50468593 ue4自带的Fsocket用起来依旧不是那么的顺手,感觉超出了我的理解范 ...

  2. Python的网络编程[0] -> socket[2] -> 利用 socket 建立 TCP/UDP 通信

    Socket 目录 socket 的 TCP/IP 通信基本建立过程 socket 的 UDP 通信基本建立过程 socket 的 UDP 广播式通信基本建立过程 socket 的多线程通信建立过程 ...

  3. C#的Socket实现UDP协议通信

    今天稍花化了一点时间,利用C#的Socket验证了UDP的通信,为接下来特地利用UDP做个分布式的通信仿真系统打下基础.众所周知,UDP 就是用户数据报协议,在互联网参考模型的第四层——传输层.与TC ...

  4. 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

    TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...

  5. Python基于socket模块实现UDP通信功能示例

    Python基于socket模块实现UDP通信功能示例 本文实例讲述了Python基于socket模块实现UDP通信功能.分享给大家供大家参考,具体如下: 一 代码 1.接收端     import ...

  6. C语言 linux环境基于socket的简易即时通信程序

    转载请注明出处:http://www.cnblogs.com/kevince/p/3891033.html      ——By Kevince 最近在看linux网络编程相关,现学现卖,就写了一个简易 ...

  7. 【Socket编程】Java通信是这样炼成的

    简介 网络无处不在,移动互联时代也早已到来,单机版程序慢慢的已没有生命力,所有的程序都要能够访问网络,比如 QQ 网络聊天程序.迅雷下载程序等,这些程序都要同网络打交道,本次将与各位小伙伴们分享的就是 ...

  8. [Socket]Socket进程间的通信

    转自:http://blog.csdn.net/giantpoplar/article/details/47657303 前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket ...

  9. Java使用多线程实现Socket多客户端的通信

    要想详细了解socket,大家请自行百度,我这里只简单介绍. 在网络中,我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程.而socket编程就是为了完成两个唯一进程之间的通信(一个是客户端, ...

随机推荐

  1. center os 6.5 vsftpd 登陆出现 530 错误拒绝 解决方法

    别管那么多 把 /etc/vsftpd/ftpusers  里面的用户名删掉就好了.

  2. android自定义相册 支持低端机不内存溢出

    1 之前在网上看的自定义相册很多时候在低端机都会内存溢出开始上代码把 首先我们要拿到图片的所有路径 cursor = context.getContentResolver().query( Media ...

  3. PPAS上运行pg_dump经过II

    这一次,我用三台机器. 其他步骤和<PPAS上运行pg_dump经过>中讲到的一样. http://www.cnblogs.com/gaojian/p/3195321.html 只是,pg ...

  4. Leetcode: Longest Palindromic Substring. java

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  5. python中使用list作为默认参数且调用时不给其赋值的问题

    最近在写代码时发现一个有趣的地方,当python中的函数使用list作为默认参数且调用时不给其赋值时,无法通过在函数中将其赋值为[]来达到清空此默认参数的目的.按照道理来说,函数f1中的list为局部 ...

  6. Linux中搭建SVNserver

    一 下载工具 1. subversion-1.6.17.tar.gz 2. subversion-deps-1.6.17.tar.gz 二 解压两个包: 1.在此之前,我已经创建了一个用户svnroo ...

  7. 在android market发布个人免费应用的步骤

    写了一段时间的android应用了,只是在自己手机上面安装. 上周申请了android developer,需要一次性25美元的程序开发注册费用.费用需要用google checkout,所以还要先申 ...

  8. MySQL通用优化 叶金荣!!!

    http://mp.weixin.qq.com/s?__biz=MjM5NDE0MjI4MA==&mid=208777870&idx=1&sn=6efddd6283e4deb3 ...

  9. Deepin Linux 安装JDK

    最近在自己的笔记本上安装了Deepin Linux,虽然使用过程中发现一些bugs,但是总体感觉还不错,准备把她作为开发系统使用.系统自带的JDK是Open JDK,但是在做JAVA开发的时候通常需要 ...

  10. 在加载模块时出现cannot insert '*.ko': Device or resource busy错误

    制作了一个模块,在加载是出现了cannot insert '*.ko': Device or resource busy错误. 原因: 是由于模块使用的是静态分配设备号,而这个设备号已经被系统中的其他 ...