如何让byte[]数组大小随Socket的Receive接收内容大小来变化
如题。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[]数组中呢。
谢谢,在线等。
[解决办法]
/// <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); }
[解决办法]
下面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); } }
[解决办法]
最好不要这样:动态变化,就会动态重新分配内存,对应通信程序是个很大负担!内存会不断增加!
一般的做法:定义一个合理的类全局的缓冲区大小!通信程序,一般有通信协议的概念,里面有数据帧的概念,
数据帧有头尾标记,你在接收处理是,根据头尾标记来处理一个完整的帧数据,有可能超过你换成区大小,这是会有多帧数据,组成完整的数据帧。
[解决办法]
其实我也建议楼主放弃 分多次传递的设计。
你在花费很多额外的工作去处理本该一次完成的工作,
可能你的受到某些限制,但是你可以争取去该别这些设置。
[解决办法]
用List<byte>,最后确认完成接收:即到达帧尾,把它一次性转换:
如:
List<byte> bytelist=new List<byte>();
............
byte[] bytearr=bytelist.ToArray();
[解决办法]
TCP接收的都是 Byte数组,你要转码才能看到,发送的是什么数据啊
你要问发送的人是怎么发的,一般不做特殊处理的都是UTF8格式的
[解决办法]
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);
}