c# - tcp 服务器在第一次循环后失败

标签 c# c sockets tcp tcpclient

如上所述,我正在尝试用 c 语言创建一个 tcp Linux 服务器来接受数据,执行一些处理然后将其发送回来。

我尝试在客户端使用的代码发送数据然后读回:

        TcpClient tcpclnt = new TcpClient();
        tcpclnt.Connect("192.168.0.14", 1235);
        NetworkStream stm = tcpclnt.GetStream();

            _signal.WaitOne();
            Image<Bgr, Byte> frame = null;
            while (_queue.TryDequeue(out frame))
            {
                if (frame != null)
                {
                    resizedBMPFrame = frame.Resize(0.5, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR).ToBitmap();
                    using (MemoryStream ms = new MemoryStream())
                    {
                        resizedBMPFrame.Save(ms, ImageFormat.Bmp);
                        byte[] byteFrame = ms.ToArray();
                        l = byteFrame.Length;
                        byte[] buf = Encoding.UTF8.GetBytes(l.ToString());
                        stm.Write(buf, 0, buf.Length);
                        stm.Write(byteFrame, 0, byteFrame.Length);
                    }
                }
                else
                {
                    Reading = false;
                }              
            int i;
            Bitmap receivedBMPFrame;
            byte[] receivedFramesize = new byte[4];
            int j = stm.Read(receivedFramesize, 0, receivedFramesize.Length);
            int receivedFramesizeint = BitConverter.ToInt32(receivedFramesize, 0);
            byte[] receivedFrame = new byte[receivedFramesizeint];
            j = stm.Read(receivedFrame, 0, receivedFrame.Length);

            using (MemoryStream ms = new MemoryStream(receivedFrame))
            {
                receivedBMPFrame = new Bitmap(ms);
                if (receivedBMPFrame != null)
                {
                    outputVideoPlayer.Image = receivedBMPFrame;
                }
                else
                {
                    Reading = false;
                }
            }
        }
    }
    stm.Close();
    tcpclnt.Close();

所以想法是它等待显示线程使用并发队列发送它正在显示的当前帧,然后它获取它,并将其设为大小的四分之一,将其转换为字节数组,然后发送其长度和然后它本身通过 TCP 套接字。

理论上,服务器获取它,执行一些处理,然后将其发回,因此它读取它的长度,然后读取新帧本身。

服务器代码如下:

while (1)
{
    int incomingframesize;

    int n;
    n = read(conn_desc, framesizebuff, 6);
    if ( n > 0)
    {       
        printf("Length of incoming frame is %s\n", framesizebuff);
    }
    else
    {
        printf("Failed receiving length\n");
        return -1;
    }
    char framebuff[atoi(framesizebuff)];

    n = read(conn_desc, framebuff, atoi(framesizebuff));
    if ( n > 0)
    {

        printf("Received frame\n");
    }
    else
    {
        printf("Failed receiving frame\n");
        return -1;
    }

    printf("Ready to write\n");

    int k = sizeof(framebuff);
    n = write(conn_desc, &k, sizeof(int));
    if (n <0)
    {
        printf("ERROR writing to socket\n");
    }
    else
    {
        printf("Return frame size is %d\n", k);
    }

    n = write(conn_desc, &framebuff, sizeof(char)*k);
    if (n <0)
    {
        printf("ERROR writing to socket\n");
    }
    frameno++;
    printf("Frames sent: %d\n", frameno);
}

所以它读取长度,然后读取实际的帧,这似乎可以工作,目前只是将其直接发送回来而不进行任何处理。然而,它似乎只适用于一个循环,如果我逐行单步执行客户端代码,服务器代码会运行一次,但在客户端读取第二次时,从服务器接收帧,服务器然后运行两次读取立即循环,无需等待另一次写入。第二次失败,似乎没有读到任何输出:

Length of incoming frame is
Failed receiving frame

没有数字,这对我来说是有道理的,因为我还没有发送另一个包含下一帧长度的写入。我只是想知道我错过了什么/为什么会这样?与第一个循环一样,它会等待来自客户端的写入命令。我想知道这是否意味着写入流中还有剩余数据,因此当它返回到顶部时,它会立即再次读取它?尽管它不会打印任何形式的数字,这对我来说意味着什么都没有......

任何帮助将不胜感激。

编辑/更新: 将服务器上的读/写部分更改为一次执行一个字节,如下所示:

while (ntotal != incomingframesize)
    {
    n = read(conn_desc, &framebuff[ntotal], sizeof(char));
    ntotal = ntotal + n;

while (i < k)
    {
    m = write(conn_desc, &framebuff[i], sizeof(char));  

这似乎解决了我遇到的问题,现在正在传输正确的数据:)

最佳答案

当客户端写入帧大小时,它使用某个对象的长度,但当服务器读取时,它总是尝试读取 6 个字符。您需要使用固定长度的帧大小!

读取时,您不能假设您获得了所需的字节数。如果>0,则返回值是实际读取的字节数。如果您收到的字节数少于您要求的字节数,则需要继续阅读,直到收到您期望的字节数。

首先读取,直到获得 6 个字节(帧大小)。

接下来读取,直到获得帧大小指示的字节数。

确保在所有位置使用相同的帧大小字节数。

编辑:

我还注意到在服务器中调用 write 时存在一个错误:

n = write(conn_desc, &framebuff, sizeof(char)*k);

framebuff 是指向数据的指针,所以您可能的意思是:

n = write(conn_desc, &framebuff[0], k);

关于c# - tcp 服务器在第一次循环后失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28561468/

相关文章:

c# - Resharper陷阱

c# - 更新绘图而不删除上一张绘图

python - 字符串变量打印不正确

.Net UDP 数据包丢失,尽管所有数据包都到达(Wireshark) - ReceiveBuffer 不是问题

c# - 查找周边上的点来表示边界/形状

c# - 如何有条件地使用 MVC Controller 注释

c - 为什么 c-faq 16.7 解决方案不考虑填充字节?

c 扫描文件夹中的新文件

C - Strcmp() 不工作

java - 绑定(bind)CXF Client源IP地址