如何让byte[]数组大小随Socket的Receive接收内容大小来变化

anya 2011-10-31 11:31:54
如题。byte[]数组大小不定长,SOCKET传输总长度不定,通过TCP/IP每次只传输500字节,使用异步传输, 总长度有时候是1000,有时候695,有时候1200这样的。主要代码如下:

private void AcceptCallback(IAsyncResult ar)
{
mse.Set();
Socket listen = ar.AsyncState as Socket;
Socket client = listen.EndAccept(ar); //对每一个侦听的客户端端口信息进行接收和回发
StateObject so = new StateObject();
so.ClientSocket = client;
client.BeginReceive(so.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, ReceiveCallback, so);
mse.WaitOne();
}


private void ReceiveCallback(IAsyncResult ar)
{

StateObject so = ar.AsyncState as StateObject;
int recv=0;
reqeustcount += 1;
recv = so.ClientSocket.EndReceive(ar);

if ((recv > 0))
{
byte[] recvBytes = new byte[recv];
}

so.ClientSocket.BeginReceive(so.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, ReceiveCallback, so);
}



这段代码其中的“recv”长度每次都是500传输一次。比如第一次传输500,第二次500,第三次500,第四次70之类的算是接收完了。每次都是一段一段的,不能累积。


我应该怎样把这四次结果都存储在一个byte[]数组中呢,还是保存在array[]数组中呢。


谢谢,在线等。
...全文
1242 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
anya 2011-11-01
  • 打赏
  • 举报
回复
谢谢大家,结贴。
指间的风 2011-10-31
  • 打赏
  • 举报
回复
如果你接收到并发请求,你的程序在处理这样的数据时,会变得很复杂。
指间的风 2011-10-31
  • 打赏
  • 举报
回复
其实我也建议楼主放弃 分多次传递的设计。
你在花费很多额外的工作去处理本该一次完成的工作,
可能你的受到某些限制,但是你可以争取去该别这些设置。
sdl2005lyx 2011-10-31
  • 打赏
  • 举报
回复
最好不要这样:动态变化,就会动态重新分配内存,对应通信程序是个很大负担!内存会不断增加!
一般的做法:定义一个合理的类全局的缓冲区大小!通信程序,一般有通信协议的概念,里面有数据帧的概念,
数据帧有头尾标记,你在接收处理是,根据头尾标记来处理一个完整的帧数据,有可能超过你换成区大小,这是会有多帧数据,组成完整的数据帧。
  • 打赏
  • 举报
回复
下面mToProcess就是你想要的

int nBytesRec = sock.EndReceive(ar);
//如果有接收到数据的话
if (nBytesRec > 0)
{
//将接收到的数据转个码,顺便转成string型
string sRecieved = Encoding.GetEncoding("utf-8").GetString(m_byBuff, 0, nBytesRec);
//声明一个字符串,用来存储解析过的字符串
string m_strLine = "";
//遍历Socket接收到的字符
/*
* * 此循环用来调整linux 和 windows在换行上标记的区别
* * 最后将调整好的字符赋予给 m_strLine
* */
for (int i = 0; i < nBytesRec; i++)
{
Char ch = Convert.ToChar(m_byBuff[i]);
switch (ch)
{
case '\r':
m_strLine += Convert.ToString("\r\n");
break;
case '\n':
break;
default:
m_strLine += Convert.ToString(ch);
break;
}
}
try
{
//获得转义后的字符串的长度
int strLinelen = m_strLine.Length;
//如果长度为零
if (strLinelen == 0)
{
//则返回"\r\n" 即回车换行
m_strLine = Convert.ToString("\r\n");
}
//建立一个流,把接收的信息(转换后的)存进 mToProcess 中
Byte[] mToProcess = new Byte[strLinelen];
for (int i = 0; i < strLinelen; i++)
mToProcess[i] = Convert.ToByte(m_strLine[i]);
// Process the incoming data
//对接收的信息进行处理,包括对传输过来的信息的参数的存取和
string mOutText = ProcessOptions(mToProcess);
//解析命令后返回 显示信息(即除掉了控制信息)
if (mOutText != "")
Console.Write(mOutText);
// Respond to any incoming commands
//接收完数据,处理完字符串数据等一系列事物之后,开始回发数据
RespondToOptions();
}
catch (Exception ex)
{
throw new Exception("接收数据的时候出错了! " + ex.Message);
}
}
anya 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 return_false 的回复:]
C# code

int nBytesRec = sock.EndReceive(ar);
//如果有接收到数据的话
if (nBytesRec > 0)
{
//将接收到的数据转个码,顺便转成string型
……
[/Quote]

我接收的是16进制数啊。比如 0x66, 0x99, 0x55, 0xAA, 0xC6, 0x83, 0x6E, 0x70, 0x13, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x3C, 0xFA, 0xF0, 0xF0, 0xF0......
  • 打赏
  • 举报
回复

int nBytesRec = sock.EndReceive(ar);
//如果有接收到数据的话
if (nBytesRec > 0)
{
//将接收到的数据转个码,顺便转成string型
string sRecieved = Encoding.GetEncoding("utf-8").GetString(m_byBuff, 0, nBytesRec);
}

用字符串接收,又有何尝不可.
anya 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zyloveyrf 的回复:]
C# code

/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="strMsg"></param>
public void Send(string strMsg)
{
byte[] arrMsg = Syste……
[/Quote]


希望能就我上面的代码提供下解决方案哈
萧炎 2011-10-31
  • 打赏
  • 举报
回复

/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="strMsg"></param>
public void Send(string strMsg)
{
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrMsgFinal = new byte[arrMsg.Length+1];

arrMsgFinal[0] = 0;//设置 数据标识位等于0,代表 发送的是 文字
arrMsg.CopyTo(arrMsgFinal, 1);

sokMsg.Send(arrMsgFinal);
}
jshi123 2011-10-31
  • 打赏
  • 举报
回复
MemoryStream ms = new MemoryStream();

private void AcceptCallback(IAsyncResult ar)
{
mse.Set();
Socket listen = ar.AsyncState as Socket;
Socket client = listen.EndAccept(ar); //对每一个侦听的客户端端口信息进行接收和回发
StateObject so = new StateObject();
so.ClientSocket = client;
client.BeginReceive(so.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, ReceiveCallback, so);
mse.WaitOne();

ms.Flush();
byte[] received = ms.ToArray();
PrintByteArray(received);
}

private void ReceiveCallback(IAsyncResult ar)
{
StateObject so = ar.AsyncState as StateObject;
int recv = 0;
reqeustcount += 1;
recv = so.ClientSocket.EndReceive(ar);

if ((recv > 0))
{
//byte[] recvBytes = new byte[recv];
ms.Write(so.Buffer, 0, recv);
}

so.ClientSocket.BeginReceive(so.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, ReceiveCallback, so);
}
assky124 2011-10-31
  • 打赏
  • 举报
回复
TCP接收的都是 Byte数组,你要转码才能看到,发送的是什么数据啊

你要问发送的人是怎么发的,一般不做特殊处理的都是UTF8格式的
anya 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 sdl2005lyx 的回复:]
引用 9 楼 anya 的回复:
我只是监听接收的部分,对方发过来的就是TCP/IP多次传输,每次500字节。1次,2次,3次,。。。。。。我想实现的就是把这几次接受的组合成一个byte[]


你不是要多次拼装吗,而且每次固定为500个字节,那你定义连个类全局变量:

List<byte> bytelist=new List<byte>();
byte[] buffer=new b……
[/Quote]


谢谢,按照你的提示我把代码修改了一下

private void ReceiveCallback(IAsyncResult ar)
{
StateObject so = ar.AsyncState as StateObject;
int recv=0;
reqeustcount += 1;
recv = so.ClientSocket.EndReceive(ar);
List<byte> bytelist = new List<byte>();
if ((recv > 0))
{

byte[] recvBytes = new byte[recv];
Array.Copy(so.Buffer, 0, recvBytes, 0, recv);
bytelist.AddRange(recvBytes); }

so.ClientSocket.BeginReceive(so.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, ReceiveCallback, so);
byte[] bytearr = bytelist.ToArray();
PrintByteArray(bytearr);

richTextBox1.BeginInvoke(new System.EventHandler(UpdateUI), "第:" + recv.ToString() + "接收数据 " + reqeustcount + "次" + strmsg);
}


可是得到的结果仍然还是一段一段的显示,如下

第:16接收数据 1次{ 0x5a 0xa5 0x69 0x96 0x9c 0x9b 0x5c 0xcc 0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x5d }

第:70接收数据 2次{ 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x69 0x9d 0x3f 0x5b }

。。。。。。。


两次就是组合不起来。
sdl2005lyx 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 anya 的回复:]
我只是监听接收的部分,对方发过来的就是TCP/IP多次传输,每次500字节。1次,2次,3次,。。。。。。我想实现的就是把这几次接受的组合成一个byte[]
[/Quote]

你不是要多次拼装吗,而且每次固定为500个字节,那你定义连个类全局变量:

List<byte> bytelist=new List<byte>();
byte[] buffer=new byte[500];
........//接收数据

bytelist.AddRange(buffer);

.......
最后,接收完毕:
byte[] allBytes=bytelist.ToArray();


anya 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 sdl2005lyx 的回复:]
用List<byte>,最后确认完成接收:即到达帧尾,把它一次性转换:

如:
List<byte> bytelist=new List<byte>();
............

byte[] bytearr=bytelist.ToArray();
[/Quote]


bytelist怎么存储的
sdl2005lyx 2011-10-31
  • 打赏
  • 举报
回复
用List<byte>,最后确认完成接收:即到达帧尾,把它一次性转换:

如:
List<byte> bytelist=new List<byte>();
............

byte[] bytearr=bytelist.ToArray();
anya 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 freesarge 的回复:]
其实我也建议楼主放弃 分多次传递的设计。
你在花费很多额外的工作去处理本该一次完成的工作,
可能你的受到某些限制,但是你可以争取去该别这些设置。
[/Quote]


我只是监听接收的部分,对方发过来的就是TCP/IP多次传输,每次500字节。1次,2次,3次,。。。。。。我想实现的就是把这几次接受的组合成一个byte[]

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧