gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 17:20:32 25 4
gpt4 key购买 nike

如上所述,我正在尝试用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com