如上所述,我试图在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));
这似乎解决了我遇到的问题,现在正在传输正确的数据:)
答案 0 :(得分:0)
当客户端写入帧大小时,它使用某个对象的长度,但是当服务器读取它时,它总是尝试读取6个字符。您需要使用固定长度的帧大小!
阅读时,您不能假设您获得的字节数与您要求的数量相同。返回值,如果> 0,则是实际读取的字节数。如果你得到的比你要求的少,你需要继续阅读,直到你收到你期望的字节数。
首先阅读,直到你有6个字节(帧大小)。
接下来阅读,直到您获得帧大小指示的字节数。
确保在所有位置使用相同数量的字节作为帧大小。
修改强>
我还注意到服务器中write
的调用中存在错误:
n = write(conn_desc, &framebuff, sizeof(char)*k);
framebuff
是指向数据的指针,因此您可能意味着:
n = write(conn_desc, &framebuff[0], k);