Как приложение C# может легко передать и передать файлы в сети?

Я не думаю, что справедливо сделать классический "текстовый редактор и консоль по сравнению с IDE", когда "текстовый редактор" действительно emacs. Большинство функций, которые типичны для IDE:s, находится также в emacs. Или возможно они даже произошли там, и современные IDE:s являются главным образом интерфейсными улучшениями/упрощениями.

Это означает, что для исходного вопроса, ответ не таким образом ясен. Это зависит от , как люди на рассматриваемом сайте используют emacs, если они главным образом используют его в качестве текстового редактора, или если они полностью выкладываются и используют пользовательские сценарии, изучают команды для соответствующих режимов, знают о коде, отмечающем и так далее.

7
задан Robinicks 9 August 2009 в 09:39
поделиться

3 ответа

Для передачи файлов / данных вы можете использовать классы TcpClient / TcpListener , которые являются хорошей абстракцией по сравнению с более жесткими функциональными возможностями сокетов. Или вы можете просто использовать приложение в качестве HTTP-сервера, используя класс HttpListener , если это проще / подходит для вашего приложения.

Для обнаружения, если у вас есть центральный сервер; тогда каждый клиент может подключаться к серверу при запуске, чтобы зарегистрироваться и получить список других онлайн-клиентов и их IP-адреса. Последующая коммуникация может происходить непосредственно между клиентами.

Вариант этой схемы - позволить центральному серверу действовать как прокси, через который проходит весь трафик между клиентами.

2
ответ дан 6 December 2019 в 23:11
поделиться

Самое замечательное в файлах и сокетах в C # то, что они оба отображаются как потоки. Копировать большой файл из одного потока в другой довольно просто:

byte[] data = new byte[1024];
while(true) {
int bytesRead = filestream.read(data,0,data.Length);
if (bytesRead==0) break;
netstream.write(data,0,bytesRead);
}

Затем просто закройте сокет, когда закончите.

Если вы хотите отправить метаданные (имена файлов, размеры) или не хотите закрывать соединение , вам нужен какой-то протокол, чтобы справиться с этим. FTP использует два отдельных сокета (один для метаданных, другой для данных; это называется внеполосной связью). Если вы находитесь в локальной сети без брандмауэров, это вполне приемлемо. С другой стороны, если вы хотите сделать интернет-передачу, открытие одного порта - достаточно сложная задача, а два - невыносимая. Если вас не слишком заботит производительность, вы можете закодировать байты в кодировке base64, что гарантирует, что они находятся в определенном диапазоне байтов. С base64 вы можете разделять сообщения символами новой строки или другими не буквенно-цифровыми символами. Затем в первом сообщении укажите имя файла, размер или что-то еще, затем отправьте данные как второе сообщение, затем отправьте сообщение «это весь файл», чтобы клиент знал, что это сделано.

Другая тактика для сообщений - использование escape-последовательность. Например, возьмите свой байтовый поток и замените каждый экземпляр '\ 0' на '\ 0 \ 0'. Теперь используйте '\ 0 \ 1', чтобы сигнализировать об окончании сообщения, которое гарантированно не будет содержаться в вашем сообщении с данными. Декодируйте '\ 0 \ 0' обратно в '\ 0' на принимающей стороне. Это достаточно хорошо работает в C, но я считаю, что на практике цикл по каждому байту может быть медленнее, чем чтение целых буферов в C #.

Лучший способ - принять какой-то протокол с адаптивной длиной. Например, отправляйте данные кусками определенного размера (скажем, 512 байт). Перед каждым фрагментом отправляйте 32-битное int, представляющее размер фрагмента, через System.BitConverter. Итак, сообщения выглядят так (на английском языке):

Here's 512 bytes:
[data]
Here's 512 bytes:
[data]
Here's 32 bytes:
[data]
Here's 4 bytes:
That was the whole file

Преимущество здесь в том, что вы можете заставить буферы копирования / чтения работать на вас (чтение по 512 байт за раз), то есть ваша пропускная способность ограничена вашим сетевым стеком, а не вашим C # код. Клиент считывает 32-битное int фиксированной длины, которое позволяет ему узнать размер буфера, который он должен использовать для следующего сегмента [data].

Вот код для написания таких сообщений:

        logger.logger.debug("Sending message of length " + length);
        byte[] clength = System.BitConverter.GetBytes(buffer.Length);
        plaintextStream.Write(clength,0,clength.Length);
        plaintextStream.Write(buffer,0,buffer.Length);
        plaintextStream.Flush();

А вот код для их чтения:

               byte[] intbuf = new byte[int_32_size];
        int offset = 0;
        while (offset < int_32_size)
        {
            int read = 0;

            read = d.plaintextStream.Read(intbuf,offset,int_32_size - offset);
            offset += read;

        }
        int msg_size = System.BitConverter.ToInt32(intbuf,0);
        //allocate a new buffer to fill the message
        byte[] msg_buffer = new byte[msg_size];
        offset = 0;
        while (offset < msg_size)
        {
            int read = 0;

            read = d.plaintextStream.Read(msg_buffer,offset,msg_size - offset);
            offset += read;
        }


        return msg_buffer;
3
ответ дан 6 December 2019 в 23:11
поделиться

Вы можете использовать класс System.Net.Sockets для связи, и у него есть метод для отправки файла Socket.SendFile .

Обновление:
это хороший пример обмена файлами и отправки файла из справки C #

5
ответ дан 6 December 2019 в 23:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: