gpt4 book ai didi

c# - 通过套接字发送和接收图像

转载 作者:行者123 更新时间:2023-11-30 21:53:27 25 4
gpt4 key购买 nike

我有一个 C# 桌面应用程序。它连接到我网络上的另一台 PC,这是一个 UWP C# 应用程序。

我正在尝试将一个或两个图像发送到我的监听套接字并进行测试,我让监听套接字将图像发回给我。

问题在于,即使我的服务器收到了最初发送回客户端的所有字节,但收到的图像大小不同。

更奇怪的是,有时返回的字节是正确的,我得到了整个图像,当我尝试发送 2 张图像时,第 1 张正常,而第 2 张不正常。

然后它将/可以恢复为没有图像被正确发送回。

我认为可能与 async/await 部分有关,但我不确定如何处理。

这是我的服务器代码:

using (IInputStream input = args.Socket.InputStream)
{
byte[] data = new byte[BufferSize];
IBuffer buffer = data.AsBuffer();
uint dataRead = BufferSize;
while (dataRead == BufferSize)
{
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
requestInBytes.AddRange(data.Take((int) buffer.Length));
dataRead = buffer.Length;
}
}
var ct = requestInBytes.Count;

然后我跳出标题信息:

int counter = 0;
counter = requestCommand[0].Length;
counter = counter + requestCommand[1].Length;
counter = counter + requestCommand[2].Length;
counter = counter + requestCommand[3].Length;
counter = counter + requestCommand[4].Length;
counter = counter + requestCommand[5].Length;
counter = counter + 6;

现在我提取图像:

var imgBody = new byte[totalBytes.Length- counter];
System.Buffer.BlockCopy(totalBytes, counter, imgBody, 0, imgBody.Length);
byteArray = imgBody;

然后只发回图片:

using (IOutputStream output = args.Socket.OutputStream)
{
using (Stream response = output.AsStreamForWrite())
{
MemoryStream stream = new MemoryStream(byteArray);
await response.WriteAsync(byteArray, 0, byteArray.Length);
await response.FlushAsync();
}
}

这是我的客户端代码:

StringBuilder sb = new StringBuilder();
foreach (var gallery in Shared.CurrentJobGallery)
{
try
{
sb.Clear();
sb.Append(GeneralTags.ACTION_ADD);
sb.Append(Shared.DLE);
sb.Append("GALLERY");
sb.Append(Shared.DLE);
sb.Append(Shared.CurrentClientId);
sb.Append(Shared.DLE);
sb.Append(gallery.Title);
sb.Append(Shared.DLE);
sb.Append(gallery.Description);
sb.Append(Shared.DLE);
sb.Append(jobRef);
sb.Append(Shared.DLE);
byte[] galleryHdr = Encoding.UTF8.GetBytes(sb.ToString());
byte[] byteArray = new byte[galleryHdr.Length + gallery.ImageData.Length];

Buffer.BlockCopy(galleryHdr, 0, byteArray, 0, galleryHdr.Length);
Buffer.BlockCopy(gallery.ImageData, 0, byteArray, galleryHdr.Length, gallery.ImageData.Length);
List<byte> requestInBytes2 = new List<byte>();
System.Diagnostics.Debug.WriteLine("SENT: " + gallery.ImageData.Length.ToString());
using (TcpClient clientSocket = new TcpClient())
{
await clientSocket.ConnectAsync(GeneralTags.RASPBERRY_PI_IP_ADDRESS, GeneralTags.RASPBERRY_PI_PORT);
using (NetworkStream serverStream = clientSocket.GetStream())
{
List<byte> requestInBytes = new List<byte>();

serverStream.Write(byteArray, 0, byteArray.Length);
serverStream.Flush();
int i;
Byte[] bytes = new Byte[1024];
do
{
i = serverStream.Read(bytes, 0, bytes.Length);
byte[] receivedBuffer = new byte[i];
Array.Copy(bytes, receivedBuffer, i);

requestInBytes2.AddRange(receivedBuffer);
} while (serverStream.DataAvailable);

}
}

using (MemoryStream ms = new MemoryStream())
{
System.Diagnostics.Debug.WriteLine("BACK: " + requestInBytes2.Count.ToString());
ms.Write(requestInBytes2.ToArray(), 0, requestInBytes2.ToArray().Length);
Shared.ViewImage(Image.FromStream(ms, true));
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}

最佳答案

您的问题是 TCP 套接字基于,而不是数据包。的确,“在线”的一切都是数据包,但是当您使用 TCP 时,您无法控制数据如何拆分为数据包或重新组合为流。

特别是,这行代码是不正确的:

await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);

根据 the docs ,您必须使用从 ReadAsync 返回的缓冲区。另请注意,此缓冲区可能是部分图像,这取决于您的代码 来检测这种情况,必要时阅读更多内容,并将这些 block 附加在一起。此外,缓冲区可能包含一个图像的一部分和下一个图像的一部分;检测并正确处理它也取决于您的代码。

出于这个原因,大多数 TCP 应用程序使用某种形式的 message framing (在我的博客上有更详细的描述)。请注意,要做到这一点非常困难。

我强烈建议您使用 SignalR 而不是原始 TCP 套接字。 SignalR 为您处理消息框架,并且它能够 self 托管(即,它不需要 ASP.NET)。

关于c# - 通过套接字发送和接收图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843646/

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