C# 从网络流中读取
C# Read from a Networkstream
我试图通过网络流发送一个对象(在我的例子中是一个图像)..然而-我没有得到完整的图像..
这是客户端代码:
private void Form1_Load(object sender, EventArgs e)
{
TcpClient c = new TcpClient();
c.Connect("10.0.0.4", 10);
NetworkStream ns = c.GetStream();
Bitmap f = GetDesktopImage();
byte[] buffer = imageToByteArray(f);
byte[] len = BitConverter.GetBytes(buffer.Length);
MemoryStream stream = new MemoryStream();
stream.Write(len, 0, len.Length);
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;
stream.CopyTo(ns);
}
如你所见,我首先将整个内容 写入常规 MemoryStream(因为我不想使用两次 NetworkStream
- 然后,我复制MemoryStream
内容进入NetworkStream
.
服务器代码:
private void Form1_Load(object sender, EventArgs e)
{
TcpListener tl = new TcpListener(IPAddress.Any, 10);
tl.Start();
TcpClient c = tl.AcceptTcpClient();
network = new NetworkStream(c.Client);
byte[] buff = new byte[4];
network.Read(buff, 0, 4);
int len = BitConverter.ToInt32(buff, 0);
buff = new byte[len];
network.Read(buff, 0, buff.Length);
pictureBox1.Image = byteArrayToImage(buff);
Thread th = new Thread(method);
}
现在,当我 运行 两个应用程序都只获取捕获图像的顶部时...这更奇怪,因为直接写入网络流非常完美...例如:
ns.Write(len, 0, len.Length);
ns.Write(buffer, 0, buffer.Length);
这会工作得很好,我会在另一边得到完整的图像..但我不想使用它两次(这只是一个例子,在我的真实项目中我必须经常使用它所以我希望尽可能减少网络使用,而不是为每个数据触发它)。
为什么仅使用 CopyTo
方法不起作用?
如有任何帮助,我将不胜感激!
谢谢
在您的服务器代码中,您忽略了 NetworkStream.Read 的结果,即实际读取的字节数。这可能比您实际请求的字节数少。您需要继续调用 Read,直到收到所需的所有字节。
您在 1 次或多次写入之间看到的差异与网络堆栈中的 buffering/timing 有关。我怀疑您只是在进行单次写入时很幸运地收到图像 - 情况并非总是如此!您需要 如上所述处理读取的结果。
代码示例:
void ReadBuffer(byte[] buffer, int offset, int count)
{
int num;
int num2 = 0;
do
{
num2 += num = _stream.Read(buffer, offset + num2, count - num2);
}
while ((num > 0) && (num2 < count));
if (num2 != count)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", count - num2));
}
我试图通过网络流发送一个对象(在我的例子中是一个图像)..然而-我没有得到完整的图像..
这是客户端代码:
private void Form1_Load(object sender, EventArgs e)
{
TcpClient c = new TcpClient();
c.Connect("10.0.0.4", 10);
NetworkStream ns = c.GetStream();
Bitmap f = GetDesktopImage();
byte[] buffer = imageToByteArray(f);
byte[] len = BitConverter.GetBytes(buffer.Length);
MemoryStream stream = new MemoryStream();
stream.Write(len, 0, len.Length);
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;
stream.CopyTo(ns);
}
如你所见,我首先将整个内容 写入常规 MemoryStream(因为我不想使用两次 NetworkStream
- 然后,我复制MemoryStream
内容进入NetworkStream
.
服务器代码:
private void Form1_Load(object sender, EventArgs e)
{
TcpListener tl = new TcpListener(IPAddress.Any, 10);
tl.Start();
TcpClient c = tl.AcceptTcpClient();
network = new NetworkStream(c.Client);
byte[] buff = new byte[4];
network.Read(buff, 0, 4);
int len = BitConverter.ToInt32(buff, 0);
buff = new byte[len];
network.Read(buff, 0, buff.Length);
pictureBox1.Image = byteArrayToImage(buff);
Thread th = new Thread(method);
}
现在,当我 运行 两个应用程序都只获取捕获图像的顶部时...这更奇怪,因为直接写入网络流非常完美...例如:
ns.Write(len, 0, len.Length);
ns.Write(buffer, 0, buffer.Length);
这会工作得很好,我会在另一边得到完整的图像..但我不想使用它两次(这只是一个例子,在我的真实项目中我必须经常使用它所以我希望尽可能减少网络使用,而不是为每个数据触发它)。
为什么仅使用 CopyTo
方法不起作用?
如有任何帮助,我将不胜感激!
谢谢
在您的服务器代码中,您忽略了 NetworkStream.Read 的结果,即实际读取的字节数。这可能比您实际请求的字节数少。您需要继续调用 Read,直到收到所需的所有字节。
您在 1 次或多次写入之间看到的差异与网络堆栈中的 buffering/timing 有关。我怀疑您只是在进行单次写入时很幸运地收到图像 - 情况并非总是如此!您需要 如上所述处理读取的结果。
代码示例:
void ReadBuffer(byte[] buffer, int offset, int count)
{
int num;
int num2 = 0;
do
{
num2 += num = _stream.Read(buffer, offset + num2, count - num2);
}
while ((num > 0) && (num2 < count));
if (num2 != count)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", count - num2));
}