【问题标题】:send byte[] data over network stream socket. c#通过网络流套接字发送 byte[] 数据。 C#
【发布时间】:2016-10-24 04:16:14
【问题描述】:

我想通过 networkstream 发送字符串 json。客户端代码

 using (var ns = new NetworkStream(socket))
{
 string json = JsonConvert.SerializeObject(listCfile, Formatting.Indented);
 byte[] jsonbytes = Encoding.UTF8.GetBytes(json);
 byte[] jsonLength = BitConverter.GetBytes(jsonbytes.Length);
 ns.Write(jsonLength, 0, jsonLength.Length);
 ns.Write(jsonbytes, 0, jsonbytes.Length);
}

jsonbytes 为字节[988324]

在服务器端

 using (var ns = new NetworkStream(socket))
 {
 byte[] byDataLength = new byte[4];
ns.Read(byDataLength, 0, 4);
int jsonLength = BitConverter.ToInt32(byDataLength, 0);
byte[] byData = new byte[jsonLength];
ns.Read(byData, 0, jsonLength);
File.WriteAllBytes("E:\\json.txt",byData);
}

byData 为字节[988324]

但我收到的 byData 与我发送的 jsonbytes 不同。

我需要一些帮助。

更新!有时它会起作用。收到的 ByData 与我发送的 jsonbytes 相同 有时它不起作用:(

【问题讨论】:

  • “它丢失了一些数据”不是对问题的有用描述。请详细说明。
  • 从客户端是jsonLength在实际数据之前发送,在服务器端建一个缓冲区来接收json数据?
  • @nura 我和你的想法一样,但我是 c# 和编码的初学者,所以你可以给我一些例子,非常感谢。
  • 双方都使用 C# 吗?建筑学怎么样?客户端是手机吗?
  • NetworkStream.Read: "Read 操作读取尽可能多的可用数据,不超过 size 参数指定的字节数"。您忽略了来自Read 的返回值,它告诉您被读取了多少字节。不能保证一侧对Write 的调用与另一侧对Read 的调用1-1 匹配。 TCP 是字节流。不是消息。

标签: c# sockets networkstream


【解决方案1】:

您可以尝试使用原始套接字发送和接收以及使用内存流和数据包结束机制来处理未知数据长度。

下面是一个 sn-p 方法,展示了使用原始套接字并在内存流中缓冲直到检测到 End-Of-Packet。

    protected const int SIZE_RECEIVE_BUFFER = 1024; /// Receive buffer size
    protected const string EOF = "!#~*|"; /// End of packet string
    MemoryStream _msPacket = new MemoryStream(); /// Memory stream holding buffered data packets
    int _delmtPtr = 0; /// Ranking pointer to check for EOF 
    Socket _baseSocket;
    public event EventHandler OnReceived;

    // TODO: -
    // Add methods to connect or accept connections.
    // When data is send to receiver, send with the same EOF defined above.
    //
    //
    public void RegisterToReceive()
    {
        byte[] ReceiveBuffer = new byte[SIZE_RECEIVE_BUFFER];
        _baseSocket.BeginReceive
        (
            ReceiveBuffer,
            0,
            ReceiveBuffer.Length,
            SocketFlags.None,
            new AsyncCallback(onReceiveData),
            ReceiveBuffer
        );
    }
    private void onReceiveData(IAsyncResult async)
    {
        try
        {
            byte[] buffer = (byte[])async.AsyncState;
            int bytesCtr = 0;
            try
            {
                if (_baseSocket != null)
                    bytesCtr = _baseSocket.EndReceive(async);
            }
            catch { }
            if (bytesCtr > 0)
                processReceivedData(buffer, bytesCtr);
            RegisterToReceive();
        }
        catch{ }
    }

    private void processReceivedData(byte[] buffer, int bufferLength)
    {
        byte[] eof = Encoding.UTF8.GetBytes(EOF);
        int packetStart = 0;
        for (int i = 0; i < bufferLength; i++)
        {
            if (buffer[i].Equals(eof[_delmtPtr]))
            {
                _delmtPtr++;
                if (_delmtPtr == eof.Length)
                {
                    var lenToWrite = i - packetStart - (_delmtPtr - 1);
                    byte[] packet = new byte[lenToWrite + (int)_msPacket.Position];

                    if (lenToWrite > 0)
                        _msPacket.Write(buffer, packetStart, lenToWrite);

                    packetStart = i + 1;
                    _msPacket.Position = 0;
                    _msPacket.Read(packet, 0, packet.Length);

                    try
                    {
                        if (OnReceived != null)
                            OnReceived(packet, EventArgs.Empty);
                    }
                    catch { }
                    _msPacket.Position = 0;
                    _delmtPtr = 0;
                }
            }
            else
            { _delmtPtr = 0; }
        }
        if (packetStart < bufferLength)
            _msPacket.Write(buffer, packetStart, bufferLength - packetStart);
        if (_msPacket.Position == 0)
            _msPacket.SetLength(0);
    }

这可以接收大长度的数据,并且与发送者的长度无关。

上面的方法只展示了如何接收数据,因此必须在原始套接字上包含其他用于连接、接受、发送数据等的方法。

【讨论】:

  • 非常感谢你,但这对我来说太复杂了。还有其他方法可以做到这一点。我的数据长度未知。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 2015-07-28
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多