服务器端
int port = 6000;
string host = "127.0.0.1";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sSocket.Bind(ipe);
sSocket.Listen(0);
Console.WriteLine("监听已经打开,请等待");
//receive message接收
Socket serverSocket = sSocket.Accept();
Console.WriteLine("连接已经建立");
string recStr = "";
byte[] recByte = new byte[4096];
int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
recStr += Encoding.ASCII.GetString(recByte, 0, bytes);//接收报文
//接收报文长度的感觉意思代码如下行
//要求发过来的长度是2字节二进制格式
int sh2 = System.BitConverter.ToInt16(recByte, 0);
//这是字节转int,但好像不是二进制的字节转的呀?
//执行得到不是想要的,只是个意思
//send message发送
Console.WriteLine("服务器端获得信息:{0}", recStr);
// recStr接收到的
//想要把接收到的报文,包括报文头长度,报文头,报文体长度,报文体原封不动再发回客户端
string sendStr = recStr;
byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
serverSocket.Send(sendByte, sendByte.Length, 0);
serverSocket.Close();
sSocket.Close();
客户端
int port = 6000;
string host = "127.0.0.1";//服务器端ip地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(ipe);
//报文头长度和报文头内容
string _header = "{"mode":"0"}";//报文头内容,拼接json格式,mode为0报文 体不加密,为1报文 体加密
short _len = (short)_header.Length;//报文头长度
//send message发送
//报文头长度要求为2字节二进制格式,这里主要是我不会的了
byte[] bslen = new byte[2];//定义2字节
bslen = BitConverter.GetBytes(_len);//二进制格式,这里也是意思,这样好像不是二进制
或这样
// bslen = Encoding.GetEncoding(936).GetBytes(Convert.ToString(_len, 2));//感觉这样是二进制了
//报文体
string bodyTpl =
@"
<Root>
<Head>
<Trxcode>{0}</Trxcode>
<count>{1}</count>
</Head>
</Root>";
string Trxcode = "中文";//交易代码
string count = "您好";//记录数量
string body = string.Format(bodyTpl, Trxcode, count);
//报文体长度
short _len2t = (short)body .Length;//报文头长度
//报文体长度要求为2字节二进制格式,这里主要是我不会的了
byte[] bslen2t = new byte[2];//定义2字节
bslen2t = BitConverter.GetBytes(_len2t);//二进制格式,这里也是意思,这样好像不是二进制
或这样
// bslen = Encoding.GetEncoding(936).GetBytes(Convert.ToString(_len2t, 2));//感觉这样是二进制了
byte[] bsheader = Encoding.ASCII.GetBytes(_header);
byte[] bsbody = Encoding.ASCII.GetBytes(body);
//这里是分开发送的,这样对吗?服务器端如何接收,这又是我不会的了
clientSocket.Send(bslen);
clientSocket.Send(bsheader);
clientSocket.Send(bslen2t);
clientSocket.Send(bsbody);
//或者合在一起发
//byte[] zh = Encoding.GetEncoding(936).GetBytes(Convert.ToString(_len, 2) + _header +Convert.ToString(_len2t, 2) + body);
// clientSocket.Send(zh);
//但这样不能用BitConverter.GetBytes(_len)这样了,总之就是倒底如何长度是2字节二进制格式
//还有就是如果长度不用2字节二进制格式,就是一个数值,那要如何发送,是分开发?还是合在一起发,搞晕了
//接收时,合在一起发的就截取,但是以字符串还是byte[],有区别吗,以byte[]怎以截取?
//分开发的,又怎么分开接收呢?
//receive message接收。客户端发出后,服务器端再原封不动发回来接收
string recStr = "";
byte[] recBytes = new byte[4096];
int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
Console.WriteLine(recStr);
clientSocket.Close();
上述服务器端和客户端建立通信,在互相发送一次信息后通信便结束,这个没有关系的
我的问题:
一,发送自定义报文,包括报文头长度,报文头,报文体长度,报文体。要怎么发送?一般发送一段字符串,就是字符串转byte[]后直接发了,但有长度,有头,有体是怎么发,就是没理解了。是分开发,还是合一起发?合一起长度怎么表示,主要是长度是2字节二进制格式。(随便问下,长度就是正常的数值,会有发送的上区别吗)。还请给出代码,最好是2字节二进制格式和就数值 两种,谢谢
二,正常发送后,怎么接收?我的代码只用了
byte[] recByte = new byte[4096];
int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
recStr += Encoding.ASCII.GetString(recByte, 0, bytes);//接收报文
这是统一接收了吧?那要怎么区分长度,头和体呢?
网上有说先取前两个字节,看看长度,就确定了后面头和体截取多长了?但我就不会怎么先取前两个字节呢?还请给出代码,谢谢
三,客户端是分开发,还是合一起发?
如分开
clientSocket.Send(bslen);
clientSocket.Send(bsheader);
合一起发
//byte[] zh = Encoding.GetEncoding(936).GetBytes(Convert.ToString(_len, 2) + _header +Convert.ToString(_len2t, 2) + body);
// clientSocket.Send(zh);
这有什么样的区别?应当用那种呢?
4,合一起发的话,长度是2字节二进制格式和头与体怎么在一起表示啊?还请给出代码,谢谢
5,分开发的话,我发现我的服务器端只接收了两次,如
clientSocket.Send(bslen);//收到
clientSocket.Send(bsheader);//收到
clientSocket.Send(bslen2t);//没收到了
clientSocket.Send(bsbody);//没收到了
这应当是我服务器端写的不对造成的,但请能讲讲原理吗?谢谢
6,如用BitConverter.GetBytes(_len)这样发对的,我长度如102,但接收后变为f了
recStr += Encoding.GetEncoding(936).GetString(recByte, 0, bytes);//这样接的
如用// bslen = Encoding.GetEncoding(936).GetBytes(Convert.ToString(_len2t, 2));接到1100110这个一共7位表示102的字符串
这要怎么解决呢,还请给出两种情况的代码,谢谢
汇总
长度2字节二进制格式与头,体怎么发送?
怎么接收时先取前2字节得到长度,2字节二进制格式与数值有区别吗
完整的自定义报文,长度,头,体,怎么发送,分开发?还是合一起发?
分开或合一起发后,怎么相应的接收?
总之就是一个自定义报文,有长度,头,体。长度想要2字节二进制格式,怎么发送和接收?发送是怎么前2字节是长度结合头与体?接收是怎么先取前2字节得到长度,再取到头和体?
还请给出代码,谢谢
16 个解决方案
#1
随便你怎么发,一起发也行分几次发都行。对于这种自定义协议的报文,可以先收2个长度字节,然后根据得到长度再去收后续字节,有多段就以此类推
#2
不知道你做网站为什么要这种需求。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
#3
没太明白您说的,如果分几次发,第一次接收是长度,然后怎么接第二次后续字节呢?
请问能给个代码吗?谢了
还有就是我发了如三次,一长度,二头,三体,这三个是一个数据的总共。我再发一个数据的总共,接收时怎么判断是新的一个数据了呢??
#4
socket这个东西不是你发几次就一定要收几次的,你可以发N次,但只要你接受的buff足够大,完全可以一行就收完,所以无需去在于收发次数。第一次收2个长度字节,然后解析得到后续还有多少数据需要接收,然后去收这点长度的数据,反复收,每收一次计算剩余长度,直到长度吻合未知。然后再接受2个长度字节,重复上述操作
#5
请问怎么做个标识,又怎么根据标识区分,主要是区分多段数据时,一段数据包括长度,头,体,多段时如何判断?
最好有几条代码,谢谢
#6
标示这种东西任何方法都可以实现,你可以自己加一些特殊字符来区分,也有更简单来的做法。
比如JSON 就是KEY VALUES的格式。你现在的光有VALUES 所以你不知道哪一个是头哪一个是体,
当你给相应的值 加上标示键后就可以区分了啊。
接收后反序列化一下就成对象了。
#7
还想请问大家个事,就是socket我用的是个asapx页面,不是一个应用程序
#8
还想请问大家个事,就是socket我用的是个asapx页面,不是一个应用程序,如果服务器那边是分开发的,比如发了三次,那我的一个aspx页面怎么接收三次呢,我试了下,只能接一次啊。
这个大家方便给个代码吗?谢了
这个大家方便给个代码吗?谢了
#9
aspx只能发 不能收....
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
#10
aspx只能发 不能收....
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
#11
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
web和服务器多次通信,要么轮询要么websocket
#12
哎,.
你既然都玩socket了. 你就应该知道 socket跟http(asp.net)有什么区别,
asp.net(web) 中是不能随便收发tcp/ip的...
因为他是长连接..http是短连接...这最起码的 你应该懂吧..(如果这你不懂那你没有继续看下去的必要了)
首先我们不说你具体协议如何..反正也没人看..只说流程.
你无非是想通过asp.net后台发送 socket 到"服务端(虽然我不知道你的服务端是不是也是"网页")".然后根据服务端的返回值做处理
明确的告诉你,那是不行的...
因为http在请求之后就没了...所以这个时候 你服务端可能还没有send 但是这个时候 tcpclient已经释放了 根本保持不了..
就算服务端在收到数据马上send 这个时候 也不一定能发过来..更何况这样做根本没意义..这根本就是"短链接"干的事.
长连接是无论何时的 都可以进行收发,否则他的存在也没有意义啊...更何况真正的项目中 这些东西都是异步的...
既然说到"无论何时" 那么显然 http是办不到的...
所以现在你就研究协议报文这种东西 对你来说 还是太早了..因为你连基本的"流程" 可能都不太清楚.
更何况你还让大家直接给你写出代码.....
你既然都玩socket了. 你就应该知道 socket跟http(asp.net)有什么区别,
asp.net(web) 中是不能随便收发tcp/ip的...
因为他是长连接..http是短连接...这最起码的 你应该懂吧..(如果这你不懂那你没有继续看下去的必要了)
首先我们不说你具体协议如何..反正也没人看..只说流程.
你无非是想通过asp.net后台发送 socket 到"服务端(虽然我不知道你的服务端是不是也是"网页")".然后根据服务端的返回值做处理
明确的告诉你,那是不行的...
因为http在请求之后就没了...所以这个时候 你服务端可能还没有send 但是这个时候 tcpclient已经释放了 根本保持不了..
就算服务端在收到数据马上send 这个时候 也不一定能发过来..更何况这样做根本没意义..这根本就是"短链接"干的事.
长连接是无论何时的 都可以进行收发,否则他的存在也没有意义啊...更何况真正的项目中 这些东西都是异步的...
既然说到"无论何时" 那么显然 http是办不到的...
所以现在你就研究协议报文这种东西 对你来说 还是太早了..因为你连基本的"流程" 可能都不太清楚.
更何况你还让大家直接给你写出代码.....
#13
aspx 基本上是处理浏览器请求时使用,asp.net (以及 IIS)其实经常会重启你的 asp.net 应用程序的另一个进程,来解决许多问题。所以 asp.net 进程经常结束,各种内存中的状态数据经常丢失,你的程序的相关内容也会丢失。
从你的问题中的代码来看,你的“服务器端”Accept 一次,然后 Receive 一次,然后不管是不是分包的部分信息,都把这个当作完整的字符串(仅仅是字符串)执行 Console.WriteLine 输出,然后 Send 一个信息,然后就关闭服务。从这个来看,基本上是一些专门摆着让你了解一些基本语法的小例子上的代码。正常的服务流程根本不是这样的。正常的服务可以 BeginAccept/Accept 上万、几十万的请求,然后获得请求之后每一个单独的信道可以单独进行 BeginReceive/Receive 而想互不干扰,并且可以处理分包信息(而不是假设每一次 Receive 的信息都是完整的消息),并且 Send 返回数据是在消息解析中的事情(解释是在异步子线程中)而并不阻塞 BeginReceive/Receive(并不等待处理完消息Send完返回值才开始)。实际上也不轻易关闭服务。
从你的“客户端”来看,基本上你的客户端不是 web 概念。你是在 asp.net 服务器上当作客户端来看待,并不是在浏览器客户端。
通讯中要处理分包的情况,也就是接收到的信息都要放到一个 List<byte> 集合中,然后每一次 Receive 之后都要检查、解析一下这个集合的 byte[ ] ,判断是否存在一个完整的消息。例如假设你的信令规定了“第一个字节是消息长度”,那么你就从这个 byte[ ] 的第一个字节来判断一下有没有足够长度的 byes;或者比如说有的信令约定用 0d、0a
两个字节表示消息结束。当你解析到一条完整的消息,才能进行处理。你不能在收到了不完整的 bytes 的时候就随便地执行 Encoding.XXXX.GetString(....) 这种操作。
从你的问题中的代码来看,你的“服务器端”Accept 一次,然后 Receive 一次,然后不管是不是分包的部分信息,都把这个当作完整的字符串(仅仅是字符串)执行 Console.WriteLine 输出,然后 Send 一个信息,然后就关闭服务。从这个来看,基本上是一些专门摆着让你了解一些基本语法的小例子上的代码。正常的服务流程根本不是这样的。正常的服务可以 BeginAccept/Accept 上万、几十万的请求,然后获得请求之后每一个单独的信道可以单独进行 BeginReceive/Receive 而想互不干扰,并且可以处理分包信息(而不是假设每一次 Receive 的信息都是完整的消息),并且 Send 返回数据是在消息解析中的事情(解释是在异步子线程中)而并不阻塞 BeginReceive/Receive(并不等待处理完消息Send完返回值才开始)。实际上也不轻易关闭服务。
从你的“客户端”来看,基本上你的客户端不是 web 概念。你是在 asp.net 服务器上当作客户端来看待,并不是在浏览器客户端。
通讯中要处理分包的情况,也就是接收到的信息都要放到一个 List<byte> 集合中,然后每一次 Receive 之后都要检查、解析一下这个集合的 byte[ ] ,判断是否存在一个完整的消息。例如假设你的信令规定了“第一个字节是消息长度”,那么你就从这个 byte[ ] 的第一个字节来判断一下有没有足够长度的 byes;或者比如说有的信令约定用 0d、0a
两个字节表示消息结束。当你解析到一条完整的消息,才能进行处理。你不能在收到了不完整的 bytes 的时候就随便地执行 Encoding.XXXX.GetString(....) 这种操作。
#14
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
不论是服务器端,还是客户端,接收消息都要处理分包情况,都是接收多次。不管所谓的 buffer 设置多大,不管是设置1M 还是1 byte,都需要处理分包(并不是设置越大越好,当然也不是设置为小于10k更好)。而你 Receive 一次,这显然是错误的流程。处理分包、多次 BeginReceive/Receive,解析消息,判断有没有收到一条完整的消息,只有等到收到了完整消息之后才能说处理消息并且发送返回值。
不管是短连接还是长连接 tcp 通讯,都要处理分包问题。不能忽视分包。对于你的短链接tcp 方式来说,“客户端”多次 Receive ,然后当收到了一条完整的返回消息,处理了收到的消息,就可以关闭连接了。这样服务器端也随后关闭了连接,所以服务器端并不需要关闭连接(或者其实也可以规定最长连接时间,超时则中断连接)。
#15
接收消息“是”使用 Receive,发送消息“是”使用 Send。但是许多人为什么成为标题党?为什么被不良培训者欺骗呢?就是因为把这个逻辑给理解“反了”!他以为只要是 Receive 就收到了完整消息,他把必要条件当做成充分条件,他不知道其实那些培训连入门都没有入门,因为没有告诉你程序设计方法,而只是告诉你一些简单语法而已。
我们从 tcp 角度来看看 http post 消息基本格式。在消息“头”的最后,有两个连续的 0d 0a 字节,然后是消息“体”,然后又是两个连续的 0d 0a 字节。只有当看到这样的信令格式,才开始解析这个恶 http 消息。
所以任何消息都有信令格式设计,最基本的知识要求。不是说你“随便发”、另一端“随便收”,就能学会通讯程序设计。最起码地要知道自己定义消息格式,在另一端能解析为完整的消息。
而 tcp 接收端(不管是服务器还是客户端)都是应该连续接收数据,处理分包,判断是否接收到一个完整消息。这应该记为一个常识知识。
我们从 tcp 角度来看看 http post 消息基本格式。在消息“头”的最后,有两个连续的 0d 0a 字节,然后是消息“体”,然后又是两个连续的 0d 0a 字节。只有当看到这样的信令格式,才开始解析这个恶 http 消息。
所以任何消息都有信令格式设计,最基本的知识要求。不是说你“随便发”、另一端“随便收”,就能学会通讯程序设计。最起码地要知道自己定义消息格式,在另一端能解析为完整的消息。
而 tcp 接收端(不管是服务器还是客户端)都是应该连续接收数据,处理分包,判断是否接收到一个完整消息。这应该记为一个常识知识。
#16
我是来看评论的,正文回复都是长篇大论啊,mark一下。
#1
随便你怎么发,一起发也行分几次发都行。对于这种自定义协议的报文,可以先收2个长度字节,然后根据得到长度再去收后续字节,有多段就以此类推
#2
不知道你做网站为什么要这种需求。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
#3
随便你怎么发,一起发也行分几次发都行。对于这种自定义协议的报文,可以先收2个长度字节,然后根据得到长度再去收后续字节,有多段就以此类推
没太明白您说的,如果分几次发,第一次接收是长度,然后怎么接第二次后续字节呢?
请问能给个代码吗?谢了
还有就是我发了如三次,一长度,二头,三体,这三个是一个数据的总共。我再发一个数据的总共,接收时怎么判断是新的一个数据了呢??
#4
还有就是我发了如三次,一长度,二头,三体,这三个是一个数据的总共。我再发一个数据的总共,接收时怎么判断是新的一个数据了呢??
socket这个东西不是你发几次就一定要收几次的,你可以发N次,但只要你接受的buff足够大,完全可以一行就收完,所以无需去在于收发次数。第一次收2个长度字节,然后解析得到后续还有多少数据需要接收,然后去收这点长度的数据,反复收,每收一次计算剩余长度,直到长度吻合未知。然后再接受2个长度字节,重复上述操作
#5
不知道你做网站为什么要这种需求。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
请问怎么做个标识,又怎么根据标识区分,主要是区分多段数据时,一段数据包括长度,头,体,多段时如何判断?
最好有几条代码,谢谢
#6
不知道你做网站为什么要这种需求。
监听和接收都需要不停调用,要不然下次有人连你,你就连不上了。
用多线程来搞。
如果你要区别着发,就要做个标识,要不然收到后你也没办法知道是头还是体。
一次性发也是需要做手脚来标示。
再不则我感觉最好做的就是把对像直接发过来,反正你全是字符,都是简单的类型。
直接弄成对象 序列化发过来 收到再反序列化就行了。
我是这样觉得。
请问怎么做个标识,又怎么根据标识区分,主要是区分多段数据时,一段数据包括长度,头,体,多段时如何判断?
最好有几条代码,谢谢
标示这种东西任何方法都可以实现,你可以自己加一些特殊字符来区分,也有更简单来的做法。
比如JSON 就是KEY VALUES的格式。你现在的光有VALUES 所以你不知道哪一个是头哪一个是体,
当你给相应的值 加上标示键后就可以区分了啊。
接收后反序列化一下就成对象了。
#7
还想请问大家个事,就是socket我用的是个asapx页面,不是一个应用程序
#8
还想请问大家个事,就是socket我用的是个asapx页面,不是一个应用程序,如果服务器那边是分开发的,比如发了三次,那我的一个aspx页面怎么接收三次呢,我试了下,只能接一次啊。
这个大家方便给个代码吗?谢了
这个大家方便给个代码吗?谢了
#9
aspx只能发 不能收....
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
#10
aspx只能发 不能收....
收的叫"服务端" 应该是一个exe 或者一个服务..而不是"网页"
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
#11
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
web和服务器多次通信,要么轮询要么websocket
#12
哎,.
你既然都玩socket了. 你就应该知道 socket跟http(asp.net)有什么区别,
asp.net(web) 中是不能随便收发tcp/ip的...
因为他是长连接..http是短连接...这最起码的 你应该懂吧..(如果这你不懂那你没有继续看下去的必要了)
首先我们不说你具体协议如何..反正也没人看..只说流程.
你无非是想通过asp.net后台发送 socket 到"服务端(虽然我不知道你的服务端是不是也是"网页")".然后根据服务端的返回值做处理
明确的告诉你,那是不行的...
因为http在请求之后就没了...所以这个时候 你服务端可能还没有send 但是这个时候 tcpclient已经释放了 根本保持不了..
就算服务端在收到数据马上send 这个时候 也不一定能发过来..更何况这样做根本没意义..这根本就是"短链接"干的事.
长连接是无论何时的 都可以进行收发,否则他的存在也没有意义啊...更何况真正的项目中 这些东西都是异步的...
既然说到"无论何时" 那么显然 http是办不到的...
所以现在你就研究协议报文这种东西 对你来说 还是太早了..因为你连基本的"流程" 可能都不太清楚.
更何况你还让大家直接给你写出代码.....
你既然都玩socket了. 你就应该知道 socket跟http(asp.net)有什么区别,
asp.net(web) 中是不能随便收发tcp/ip的...
因为他是长连接..http是短连接...这最起码的 你应该懂吧..(如果这你不懂那你没有继续看下去的必要了)
首先我们不说你具体协议如何..反正也没人看..只说流程.
你无非是想通过asp.net后台发送 socket 到"服务端(虽然我不知道你的服务端是不是也是"网页")".然后根据服务端的返回值做处理
明确的告诉你,那是不行的...
因为http在请求之后就没了...所以这个时候 你服务端可能还没有send 但是这个时候 tcpclient已经释放了 根本保持不了..
就算服务端在收到数据马上send 这个时候 也不一定能发过来..更何况这样做根本没意义..这根本就是"短链接"干的事.
长连接是无论何时的 都可以进行收发,否则他的存在也没有意义啊...更何况真正的项目中 这些东西都是异步的...
既然说到"无论何时" 那么显然 http是办不到的...
所以现在你就研究协议报文这种东西 对你来说 还是太早了..因为你连基本的"流程" 可能都不太清楚.
更何况你还让大家直接给你写出代码.....
#13
aspx 基本上是处理浏览器请求时使用,asp.net (以及 IIS)其实经常会重启你的 asp.net 应用程序的另一个进程,来解决许多问题。所以 asp.net 进程经常结束,各种内存中的状态数据经常丢失,你的程序的相关内容也会丢失。
从你的问题中的代码来看,你的“服务器端”Accept 一次,然后 Receive 一次,然后不管是不是分包的部分信息,都把这个当作完整的字符串(仅仅是字符串)执行 Console.WriteLine 输出,然后 Send 一个信息,然后就关闭服务。从这个来看,基本上是一些专门摆着让你了解一些基本语法的小例子上的代码。正常的服务流程根本不是这样的。正常的服务可以 BeginAccept/Accept 上万、几十万的请求,然后获得请求之后每一个单独的信道可以单独进行 BeginReceive/Receive 而想互不干扰,并且可以处理分包信息(而不是假设每一次 Receive 的信息都是完整的消息),并且 Send 返回数据是在消息解析中的事情(解释是在异步子线程中)而并不阻塞 BeginReceive/Receive(并不等待处理完消息Send完返回值才开始)。实际上也不轻易关闭服务。
从你的“客户端”来看,基本上你的客户端不是 web 概念。你是在 asp.net 服务器上当作客户端来看待,并不是在浏览器客户端。
通讯中要处理分包的情况,也就是接收到的信息都要放到一个 List<byte> 集合中,然后每一次 Receive 之后都要检查、解析一下这个集合的 byte[ ] ,判断是否存在一个完整的消息。例如假设你的信令规定了“第一个字节是消息长度”,那么你就从这个 byte[ ] 的第一个字节来判断一下有没有足够长度的 byes;或者比如说有的信令约定用 0d、0a
两个字节表示消息结束。当你解析到一条完整的消息,才能进行处理。你不能在收到了不完整的 bytes 的时候就随便地执行 Encoding.XXXX.GetString(....) 这种操作。
从你的问题中的代码来看,你的“服务器端”Accept 一次,然后 Receive 一次,然后不管是不是分包的部分信息,都把这个当作完整的字符串(仅仅是字符串)执行 Console.WriteLine 输出,然后 Send 一个信息,然后就关闭服务。从这个来看,基本上是一些专门摆着让你了解一些基本语法的小例子上的代码。正常的服务流程根本不是这样的。正常的服务可以 BeginAccept/Accept 上万、几十万的请求,然后获得请求之后每一个单独的信道可以单独进行 BeginReceive/Receive 而想互不干扰,并且可以处理分包信息(而不是假设每一次 Receive 的信息都是完整的消息),并且 Send 返回数据是在消息解析中的事情(解释是在异步子线程中)而并不阻塞 BeginReceive/Receive(并不等待处理完消息Send完返回值才开始)。实际上也不轻易关闭服务。
从你的“客户端”来看,基本上你的客户端不是 web 概念。你是在 asp.net 服务器上当作客户端来看待,并不是在浏览器客户端。
通讯中要处理分包的情况,也就是接收到的信息都要放到一个 List<byte> 集合中,然后每一次 Receive 之后都要检查、解析一下这个集合的 byte[ ] ,判断是否存在一个完整的消息。例如假设你的信令规定了“第一个字节是消息长度”,那么你就从这个 byte[ ] 的第一个字节来判断一下有没有足够长度的 byes;或者比如说有的信令约定用 0d、0a
两个字节表示消息结束。当你解析到一条完整的消息,才能进行处理。你不能在收到了不完整的 bytes 的时候就随便地执行 Encoding.XXXX.GetString(....) 这种操作。
#14
aspx是能收的,我测试通过,就是aspx发多次时,服务器端返回多次,可aspx只接收一次,想请问有什么方法,aspx也可以接收多次??
不论是服务器端,还是客户端,接收消息都要处理分包情况,都是接收多次。不管所谓的 buffer 设置多大,不管是设置1M 还是1 byte,都需要处理分包(并不是设置越大越好,当然也不是设置为小于10k更好)。而你 Receive 一次,这显然是错误的流程。处理分包、多次 BeginReceive/Receive,解析消息,判断有没有收到一条完整的消息,只有等到收到了完整消息之后才能说处理消息并且发送返回值。
不管是短连接还是长连接 tcp 通讯,都要处理分包问题。不能忽视分包。对于你的短链接tcp 方式来说,“客户端”多次 Receive ,然后当收到了一条完整的返回消息,处理了收到的消息,就可以关闭连接了。这样服务器端也随后关闭了连接,所以服务器端并不需要关闭连接(或者其实也可以规定最长连接时间,超时则中断连接)。
#15
接收消息“是”使用 Receive,发送消息“是”使用 Send。但是许多人为什么成为标题党?为什么被不良培训者欺骗呢?就是因为把这个逻辑给理解“反了”!他以为只要是 Receive 就收到了完整消息,他把必要条件当做成充分条件,他不知道其实那些培训连入门都没有入门,因为没有告诉你程序设计方法,而只是告诉你一些简单语法而已。
我们从 tcp 角度来看看 http post 消息基本格式。在消息“头”的最后,有两个连续的 0d 0a 字节,然后是消息“体”,然后又是两个连续的 0d 0a 字节。只有当看到这样的信令格式,才开始解析这个恶 http 消息。
所以任何消息都有信令格式设计,最基本的知识要求。不是说你“随便发”、另一端“随便收”,就能学会通讯程序设计。最起码地要知道自己定义消息格式,在另一端能解析为完整的消息。
而 tcp 接收端(不管是服务器还是客户端)都是应该连续接收数据,处理分包,判断是否接收到一个完整消息。这应该记为一个常识知识。
我们从 tcp 角度来看看 http post 消息基本格式。在消息“头”的最后,有两个连续的 0d 0a 字节,然后是消息“体”,然后又是两个连续的 0d 0a 字节。只有当看到这样的信令格式,才开始解析这个恶 http 消息。
所以任何消息都有信令格式设计,最基本的知识要求。不是说你“随便发”、另一端“随便收”,就能学会通讯程序设计。最起码地要知道自己定义消息格式,在另一端能解析为完整的消息。
而 tcp 接收端(不管是服务器还是客户端)都是应该连续接收数据,处理分包,判断是否接收到一个完整消息。这应该记为一个常识知识。
#16
我是来看评论的,正文回复都是长篇大论啊,mark一下。