2015-09-27 4 views
6

Я создал простой сервер, использующий программирование сокетов на C#, который получит файл со стороны клиента. Мой сегмент кода кода приведен ниже.Отправка некоторых ограничений клиенту с сервера в C#

Я хочу добавить некоторые ограничения. Я хочу сделать ограничение на размер файла (например, 4   КБ или 2   КБ) и допустимые форматы файлов (такие как .doc, .txt, .cpp и т. Д.), Которые будут отправлены клиенту, как только клиент подключается к серверу, чтобы клиент мог отправлять файлы соответствующим образом. Как я это сделаю?

Пример Сегмент кода:

using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Net.Sockets; 
using System.IO; 
using System.Text; 

namespace FileTransfer 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Listen on port 1234 

      TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234); 
      tcpListener.Start(); 

      Console.WriteLine("Server started"); 

      //Infinite loop to connect to new clients 
      while (true) 
      { 
       // Accept a TcpClient 
       TcpClient tcpClient = tcpListener.AcceptTcpClient(); 
           Console.WriteLine("Connected to client"); 
       byte[] data = new byte[1024]; 
       NetworkStream ns = tcpClient.GetStream(); 
       int recv = ns.Read(data, 0, data.Length); 
       StreamReader reader = new StreamReader(tcpClient.GetStream()); 

       //Will add some lines to add restrictions... 

      } 
     } 
    } 
} 

Какие дополнительные линии мне придется добавить код, чтобы отправить ограничения клиенту?

+1

Чтобы ограничить размер файла, просто добавьте общий счетчик размера данных, например «int counter = 0; counter + = recv;». Затем, если предел превысил клиент-клиент с соответствующим сообщением. –

+0

Я просто хочу отправить размер файла и допустимые форматы файлов клиенту как sson при подключении клиента, чтобы клиент мог соответственно отправлять файлы @Alek Depler –

+0

Hm, тогда вам нужно создать свой собственный клиент-серверный протокол. Как клиент, так и сервер могут отправлять данные друг другу, вам необходимо разделить все данные на два типа: инструкции по техническому протоколу и сами данные. Ответ «CodeCaster» верен –

ответ

3

Вы, кажется, делаете классическую ошибку сокета. Данный код и объяснение, по-видимому, предполагают, что дескрипторы сокетов в сообщениях. Они не. При использовании этого способа вы используете streaming internet sockets, которые обеспечивают поток , а не сообщения.

Вы не показываете код, который выполняет фактическую отправку, поэтому я предполагаю, что вы просто перекачиваете данные файла на другую сторону и закрываете соединение. Как еще вы узнаете, что успешно передали весь файл?

Этот набор правил, которым клиент и сервер должен следовать для полезного обмена данными через сокеты, называется application protocol. У вас будет, он должен иметь один, иначе вы просто будете отправлять данные в $ божество, знает где, и вы не будете контролировать его вообще. Это означает, что сервер и клиент не узнают, что происходит, они просто будут отправлять и получать данные и надеяться, что все будет хорошо. Таким образом, нет «нескольких строк», которые вы должны добавить в свой код, вам придется полностью его перестроить.

Существует множество способов определить протокол приложения и множество вариантов на выбор, поэтому я покажу вам произвольное: текстовое объяснение сообщений с префиксом идентификатора и длины полезной нагрузки (если применимо), как в неопределенных числовых переменных. Например, вы можете выбрать малозначные четырехбайтовые целые числа без знака.

Сообщения в этом формате известны как "Type/Length/Value" or TLV. Таким образом, мы определяем эти сообщения:

ID Name   Direction   Description     Payload 
1 ServerHello Server -> Client The server sends this message None. 
            to every connecting client. Or maybe server or 
                    protocol version. 
2 MaxUpload Server -> Client Sent after the ServerHello. Maximum upload size 
                    in bytes. 
3 AllowedExts Server -> Client Allowed upload extensions,  The allowed extensions. 
            comma-separated. Sent after 
            MaxUpload message. 
10 IncomingFile Client -> Server There's a file coming.   The file name. 
11 FileUpload Client -> Server The file to upload.   The file data. 
            Sent after IncomingFile. 

Теперь все, что требуется для реализации этого протокола приложений в сервер и клиент, и вы сделали.

Вы также должны решить, что делать, если клиент или сервер не придерживаются прототола. Он может, например, отправить сообщение, которое невозможно разобрать, неизвестный идентификатор сообщения, длину сообщения, которую вы не хотите поддерживать, сообщение об ошибке (FileUpload перед IncomingFile) или сообщение, которое не является соответствуют сообщениям, отправленным ранее, например, клиент, загружающий больший файл, чем сервер, который сказал, что он примет или недействительное расширение. Вы также должны думать о «подтверждении» или ответах, например, о том, что сервер говорит клиенту «ОК, вперед, отправьте следующее сообщение».

В целом, это очень широкий вопрос и не ответил легко. Я попытался обратиться к этому в своем комментарии к вашему вопросу, который был удален. Итак, у вас есть свой ответ.

Об этом можно узнать об этом в Интернете, например Beej's Guide to Network Programming, по ссылке Giorgi (обязательно прочтите весь путеводитель) и Stephen Cleary's blog.

4

В основном я думаю, что в основном вам нужно две вещи:

  • определяют прикладной протокол, как это предлагается в другой ответ

  • и обрабатывать частичное чтение/запись

Для обработки частичного чтения (не уверен, насколько такая функция необходима для write), вы можете использовать функцию, такую ​​как below:

public static void ReadWholeArray (Stream stream, byte[] data) 
{ 
    int offset=0; 
    int remaining = data.Length; 
    while (remaining > 0) 
    { 
     int read = stream.Read(data, offset, remaining); 
     if (read <= 0) 
      throw new EndOfStreamException 
       (String.Format("End of stream reached with {0} bytes left to read", remaining)); 
     remaining -= read; 
     offset += read; 
    } 
} 

Вещь традиционный Stream.Read() не гарантирует читать столько байт, как вы сказали это, этот метод с другой стороны, будет обеспечивать, чтобы прочитать столько байт, сколько указано в параметре data.Length. Таким образом, вы можете использовать такую ​​функцию для реализации требуемого протокола приложения.

Некоторой соответствующая информация о таких прикладных протоколах вы найдете here слишком


Хорошо это, например, как сервер может послать ограничение на длину файла и расширение файла:

// Send string 
string ext = ".txt"; 
byte [] textBytes = Encoding.ASCII.GetBytes(ext); 
ns.Write(textBytes, 0, textBytes.Length); 

// Now, send integer - the file length limit parameter 
int limit = 333; 
byte[] intBytes = BitConverter.GetBytes(limit); 
ns.Write(intBytes, 0, intBytes.Length); // send integer - mind the endianness 

Но вам по-прежнему нужен какой-то протокол, иначе вы должны позволить клиенту прочитать «полный» поток и проанализировать эти данные позже, как нет, что не является тривиальным, если данные не имеют фиксированной длины и т. Д. в противном случае, как клиент будет различать, какая часть сообщения является текстом, какое целое?

+0

Имейте upvote для ссылки на руководство Beej. Любой, даже отдаленно заинтересованный в сетевом программировании, должен был прочитать это руководство хотя бы один раз. – CodeCaster

+0

@CodeCaster: Да, действительно, спасибо. Это руководство содержит полезную информацию. OP должен будет обрабатывать частичную передачу/получение, и подумайте о некотором протоколе, как вы предлагаете, или TLV и т. Д. –

+0

Протокол, который я предлагаю _is_ TLV, AFAIK. :-) – CodeCaster

Смежные вопросы