大家好,我有一个大问题:我创建了一个Windows窗体,用作服务器,侦听连接到同一专用网络的某些摄像机发送的TCP消息。 每个摄像机在摄像机检测到某些东西时都会向服务器发送一条tcp消息,服务器必须连续工作而不冻结gui接口,并且必须处理每个TCP消息。该数据的处理包括保存由发送方相机拍摄的图像。服务器将这些图像保存到文件夹中,这是我的问题: 服务器无法保存每个图像的正确性:看起来在传输过程中丢失了一些字节,但是我认为所有字节都丰富了服务器,发生了更深的事情。也许这是我对异步/等待服务器进行编程的方式?
我有一个TcpListener列表,因为我必须使用更多的服务器,每个选项卡一个。
这里保存的图像看起来像 https://imgur.com/xtlgHPk https://imgur.com/CcvWbDH
如您所见,除了某人由于某些未知原因之外,并未完全保存 https://imgur.com/G25UPSS
public void TcpServer(int port)
{
IPAddress ipAddress = null;
string hostName = Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
for (int i = 0; i < ipHostInfo.AddressList.Length; ++i)
{
if (ipHostInfo.AddressList[i].AddressFamily ==
AddressFamily.InterNetwork)
{
ipAddress = ipHostInfo.AddressList[i];
_listener.Add( new TcpListener(ipAddress, port));
ReceiveDataAsync();
break;
}
}
if (ipAddress == null)
throw new Exception("No IPv4 address for server");
}
private async void ReceiveDataAsync()
{
try
{
_listener[tbServer.SelectedIndex].Start();
while (true)
{
var tcpClient = await _listener[tbServer.SelectedIndex].AcceptTcpClientAsync();
ReadDataFromClientAsync(tcpClient);
}
}
catch (Exception e)
{
MessageBox.Show("Errore: ", e.Message.ToString());
}
}
private async Task ReadDataFromClientAsync(TcpClient client)
{
try
{
using (NetworkStream stream=client.GetStream())
{
int selectedTabIndex, indexOfPort;
string endPoint;
while (client.Connected)
{
int count = 0;
var countBytes = new byte[4];
for (int i = 0; i < 6; i++)
{
count = await stream.ReadAsync(countBytes, 0, countBytes.Length);
}
//The data dimension of the TCP message is into his header, 24th byte.
if (count == 0)
{
break;
}
byte[] bytes = new byte[BitConverter.ToUInt32(countBytes, 0)];
await stream.ReadAsync(bytes, 0, bytes.Length);
indexOfPort = Settings.getIndexOfPort(client.Client.LocalEndPoint.ToString());
endPoint = client.Client.RemoteEndPoint.ToString();
selectedTabIndex = Settings.getIndexOfPort(client.Client.LocalEndPoint.ToString());
updateGui("entry", indexOfPort,endPoint);
BufferData bufferService = new BufferData();
CameraMessage cameraMessage = await bufferService.writeBufferData(bytes.ToList());
if (cameraMessage == null)
return;
//doing some stuff
msgToShow = await bufferService.SaveImageFromCamera(cameraMessage);
//doing other stuff
}
client.Close();
closeCommunication(selectedTabIndex,indexOfPort,endPoint);
}
}
}
catch (IOException e)
{
updateGui("stop");
}
}
BufferData类:
public class BufferData
{
public async Task<CameraMessage> writeBufferData(List<byte> bytesList)
{
CameraMessage cameraMessage = new CameraMessage();
try
{
int num = 0;
int startSubData = 0;
for (int startData = 0; startData < bytesList.Count-8; startData = startSubData + num)
{
int codeDataMessage = BitConverter.ToInt32(bytesList.GetRange(startData, 4).ToArray(), 0);
int indexDataSize = startData + 4;
int SizeDataMessage = BitConverter.ToInt32(bytesList.GetRange(indexDataSize, 4).ToArray(), 0);
startSubData = indexDataSize + 4;
byte[] array = bytesList.GetRange(startSubData, SizeDataMessage).ToArray();
num = 0;
switch (codeDataMessage)
{
case 14020:
cameraMessage.image = await this.Base64ToImage(array);
num = this.OffSetStringType(SizeDataMessage);
break;
}
}
return cameraMessage;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
return null;
}
}
public async Task<string> SaveImageFromCamera( CameraMessage cameraMessage)
{
string path = Settings.pathFolder + cameraMessage.ld_I_SN + @"\Images\";
string res;
if (!Directory.Exists(Settings.pathFolder+cameraMessage.ld_I_SN))
{
Directory.CreateDirectory(Settings.pathFolder + cameraMessage.ld_I_SN + @"\Images");
}
try
{
await Task.Run(() => { cameraMessage.image.Save(path + cameraMessage.ld_I_FILENAME, ImageFormat.Jpeg); });
res = "#3 - OK - IMMAGINE SALVATA CON SUCCESSO";
cameraMessage.image.Dispose();
return res;
}
catch (Exception ex)
{
res = "#3 - ERR - IMMAGINE NON SALVATA";
return res;
}
}
public async static Task<Image> Base64ToImage(byte[] imageBytes)
{
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
return System.Drawing.Image.FromStream(ms, true);
}
}
答案 0 :(得分:0)
您的核心问题是,假设套接字读取将读取您要求的所有字节。那不是套接字读取的工作方式。
调用await stream.ReadAsync(bytes, 0, bytes.Length)
时,流将从1
到bytes.Length
读取任意数量的字节。它将返回实际读取的字节数。只要没有完全读取缓冲区,就需要考虑并重新读取。
请注意,必须同时对标头字节和有效负载字节进行此操作。