Проблема с вашим кодом заключается в том, что клиент закрывает соединение до того, как серверу удастся получить все данные.Вы должны сообщить серверу о длине вашего сообщения.Это называется «Фрейминг сообщения».
Решение
- Запишите длину сообщения перед его содержимым и прочитайте его на стороне сервера.
- Выделите буфер на сервере с размером длины сообщения.
- Чтение содержимого сообщения.
Необязательный шаг: чтобы убедиться, что у нас не будет никаких исключений Socket.клиент ждет сервера, пока он не получит все данные.Сервер закрывает соединение.
Код клиента:
static void Main(string[] args)
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 6666);
NetworkStream clientNetworkStream = client.GetStream();
string fileContent = FileBase64Encoding(@"D:\Download\AtomSetup-x64.exe");
byte[] fileBytes = Encoding.ASCII.GetBytes(fileContent);
// byte[] fileLength = Encoding.ASCII.GetBytes(fileBytes.Length.ToString());
Console.WriteLine(fileBytes.Length);
// Write the length of a message
var integerBytes = BitConverter.GetBytes(fileBytes.Length); // integer has 4 bytes
clientNetworkStream.Write(integerBytes, 0, integerBytes.Length);
// Write the contents
clientNetworkStream.Write(fileBytes, 0, fileBytes.Length);
Console.WriteLine("Send");
// Wait for server to finish receiving
clientNetworkStream.ReadByte();
Console.WriteLine("Connection closed");
}
static string FileBase64Encoding(string path)
{
byte[] fileBytes = File.ReadAllBytes(path);
string fileBase64String = Convert.ToBase64String(fileBytes);
return fileBase64String;
}
Код сервера:
class Program
{
static void Main(string[] args)
{
TcpListener serverListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 6666);
serverListener.Start();
TcpClient tcpClient = serverListener.AcceptTcpClient();
Console.WriteLine(">>> Receiving");
byte[] clientBuffer;
using (NetworkStream clientNStream = tcpClient.GetStream())
{
int i;
string received = "";
byte[] integerBytes = new byte[sizeof(int)];
clientNStream.Read(integerBytes, 0, integerBytes.Length); // receive message length
int messageLength = BitConverter.ToInt32(integerBytes, 0);
Console.WriteLine("Received message length: {0}", messageLength);
clientBuffer = new byte[messageLength]; // allocate buffer
clientNStream.Read(clientBuffer, 0, clientBuffer.Length); // read string contents
Console.WriteLine("Received all the data");
// we're done
Console.WriteLine("Closing connection");
tcpClient.Close();
received = Encoding.ASCII.GetString(clientBuffer, 0, clientBuffer.Length);
File.WriteAllText(@"E:\receivedData.txt", received);
Console.WriteLine(">>>Done");
}
}
}
Как вы можетеувидеть код для сервера теперь проще.
В идеале вам нужен более продвинутый механизм создания сообщений, который может разбивать ваше сообщение на гораздо более мелкие куски и записывать напрямую в файл, потому что у вас не хватит памяти длядействительно большие файлы и всегда хорошая идея разбивать большие сообщения на более мелкие куски.