Начиная с небольшого приложения сокетов для передачи файлов в C# (в основном, пример кода MS). Возникли проблемы с ManualResetEvent.WaitOne(). Я называю это внутри foreach loop, так что, возможно, это проблема.
В любом случае я пытаюсь заказать/заблокировать вызовы BeginSend, чтобы они начали после успешной передачи файла. Но кажется, что, хотя я вызываю WaitOne() после каждого BeginSend, они выходят из строя.Передача файла сервера клиента
Вот пример:
public class AsynchronousClient {
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
...
private static void SendAll(Socket client, String path)
{
String[] files = GetFiles(path);
int i = 0;
foreach(String file in files){
Console.WriteLine("STEP 1 - Files left: {0}", files.Length - i);
SendFile(client, Path.GetFullPath(file), files.Length - i);
sendDone.WaitOne();
i++;
}
}
private static void SendFile(Socket client, String path, int FilesLeft)
{
byte[] filesLeft = BitConverter.GetBytes((Int64)FilesLeft);
byte[] fileData = File.ReadAllBytes(path);
byte[] fileLength = BitConverter.GetBytes((Int64) fileData.Length);
byte[] fileMD5;
using (MD5 md5Hash = MD5.Create())
{
fileMD5 = md5Hash.ComputeHash(fileData);
}
byte[] filepathdata = Encoding.Unicode.GetBytes(path);
byte[] filepathLength = BitConverter.GetBytes((Int16)filepathdata.Length);
byte[] byteData = filesLeft.Concat(fileLength).Concat(fileMD5).Concat(filepathLength).Concat(filepathdata).Concat(fileData).ToArray();
Console.WriteLine("STEP 2 - File length: {0}", fileData.Length);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("STEP 3 - Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
... и вот (из) порядок действий:
STEP 1 - Files left: 16
STEP 2 - File length: 432759
STEP 3 - Sent 433033 bytes to server.
STEP 1 - Files left: 15
STEP 2 - File length: 262623
STEP 1 - Files left: 14
STEP 3 - Sent 262897 bytes to server.
STEP 2 - File length: 459683
STEP 1 - Files left: 13
STEP 2 - File length: 369381
STEP 1 - Files left: 12
STEP 2 - File length: 271126
STEP 1 - Files left: 11
STEP 3 - Sent 459957 bytes to server.
STEP 3 - Sent 369679 bytes to server.
STEP 2 - File length: 1647983
STEP 1 - Files left: 10
STEP 2 - File length: 24761
STEP 1 - Files left: 9
STEP 3 - Sent 25049 bytes to server.
STEP 3 - Sent 271424 bytes to server.
STEP 2 - File length: 858717
STEP 1 - Files left: 8
STEP 2 - File length: 214031
STEP 1 - Files left: 7
STEP 2 - File length: 531963
STEP 1 - Files left: 6
STEP 2 - File length: 227950
STEP 1 - Files left: 5
STEP 2 - File length: 394068
STEP 1 - Files left: 4
STEP 2 - File length: 243546
STEP 1 - Files left: 3
STEP 2 - File length: 173656
STEP 1 - Files left: 2
STEP 2 - File length: 712417
STEP 1 - Files left: 1
STEP 3 - Sent 1648279 bytes to server.
STEP 2 - File length: 1631924
STEP 3 - Sent 859001 bytes to server.
STEP 3 - Sent 214309 bytes to server.
STEP 3 - Sent 532239 bytes to server.
STEP 3 - Sent 228226 bytes to server.
STEP 3 - Sent 394346 bytes to server.
STEP 3 - Sent 243822 bytes to server.
STEP 3 - Sent 173936 bytes to server.
STEP 3 - Sent 712701 bytes to server.
STEP 3 - Sent 1632220 bytes to server.
ReceiveCallback: bytesRead <= 0
Response received : OK
Дело заключается в следующем: несмотря на то, что эта процедура не соответствует порядку, данные файла не повреждены на стороне сервера. Похоже, что его можно будет много раз называть BeginSend, прежде чем он закончится, но я бы предпочел, чтобы дождался, когда файл перейдет на сервер, прежде чем начать новую передачу.
Как вы создаете экземпляр 'ManualResetEvent'? можете ли вы добавить фрагмент кода? –
Я добавил код для экземпляра ManualResetEvent. – steakoverflow