Передача файлов по TCP C#
На C# хочу передать файл по TCP. В гугле есть куча примеров, но они все в подобных этому вопросах, ответом в которых является совет: "Передавайте сначала длинну, а потом уже сам файл". Подскажите, пожалуйста, а лучше пример, как передавать файлы по TCP. Достаточно по локальной сети. Спасибо!
Ответы (1 шт):
Ну вот вам простейший клиент и сервер на C# 9, без проверки на ошибки и с захардкодированными параметрами. При подсоединении клиента сервер тут же шлёт ему предзаданный файл, а клиент принимает файл и записывает его на диск.
Сервер:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
IPAddress localAddress = IPAddress.Loopback;
const int localPort = 7777;
const string filename = "test.txt";
var server = new TcpListener(localAddress, localPort);
server.Start();
while (true)
{
var client = await server.AcceptTcpClientAsync();
_ = Task.Run(() => Serve(client, filename));
}
static async Task Serve(TcpClient client, string filename)
{
using var _ = client;
var stream = client.GetStream();
using var file = File.OpenRead(filename);
var length = file.Length;
byte[] lengthBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(length));
await stream.WriteAsync(lengthBytes);
await file.CopyToAsync(stream);
}
Клиент:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
IPAddress serverAddress = IPAddress.Loopback;
const int serverPort = 7777;
string filename = "test.txt";
using var client = new TcpClient(serverAddress.ToString(), serverPort);
var stream = client.GetStream();
byte[] buf = new byte[65536];
await ReadBytes(sizeof(long));
long remainingLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(buf, 0));
using var file = File.Create(filename);
while (remainingLength > 0)
{
int lengthToRead = (int)Math.Min(remainingLength, buf.Length);
await ReadBytes(lengthToRead);
await file.WriteAsync(buf, 0, lengthToRead);
remainingLength -= lengthToRead;
}
async Task ReadBytes(int howmuch)
{
int readPos = 0;
while (readPos < howmuch)
{
var actuallyRead = await stream.ReadAsync(buf, readPos, howmuch - readPos);
if (actuallyRead == 0)
throw new EndOfStreamException();
readPos += actuallyRead;
}
}
Что клиент, что сервер настолько просты, что даже классы не нужны.
Если будете использовать сервер между хостами, не забудьте открыть порт при помощи
netsh http add urlacl http://+:7777/ user=%USERDOMAIN%\%USERNAME%
в админской консоли.