第一次循环后tcp服务器失败

时间:2015-02-17 12:26:26

标签: 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

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

非常感谢任何帮助。

EDIT / UPDATE: 更改了服务器上的读/写部分,一次执行一个字节,如下所示:

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));  

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

1 个答案:

答案 0 :(得分:0)

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

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

首先阅读,直到你有6个字节(帧大小)。

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

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

修改

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

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

framebuff是指向数据的指针,因此您可能意味着:

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