2015-09-27 8 views
6

私はクライアント側からファイルを受け取るC#でソケットプログラミングを使って簡単なサーバを作成しました。私のサンプルコードセグメントは以下の通りです。C#でサーバからクライアントにいくつかの制約を送信する

いくつかの制限を追加したいと思います。私はファイルサイズ(4   KBまたは2   KBなど)と許容されるファイル形式(.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

私はちょうどクライアントがそれに応じて@Alek Depler –

+0

Hmファイルを送ることができるようにクライアントが接続するようにssonとしてクライアントにファイルサイズと許容されるファイル形式を送信したい、そしてあなた自身のクライアントサーバープロトコルを作成する必要があります。クライアントとサーバーの両方が相互にデータを送信できるため、すべてのデータを技術プロトコルの指示とデータその2つのタイプで分割する必要があります。 "CodeCaster"の答えは正しい –

答えて

3

あなたは古典的なソケットミスをしているようです。与えられたコードと説明は、ソケット内でのメッセージの扱いを想定しているようです。 はありません。この方法で使用すると、メッセージではなく、ストリームを提供するstreaming internet socketsを使用しています。

実際の送信を行うコードは表示されません。そのため、ファイルのデータを他の側に送信して接続を終了すると思います。ファイル全体を正常に転送したことをどのように知っていますか?

ソケットを介してデータを効果的に交換するためにクライアントとサーバーが従わなければならないこの一連のルールは、application protocolと呼ばれます。 には1つ持っていなければなりません。そうでないと、$ deityにデータを送信するだけでどこを知ることができますか?これはサーバーやクライアントが何が起こっているかを知っていることを意味し、データを送受信するだけですべてがうまくいくことを期待しています。したがって、コードに追加する必要がある「数行」はありません。完全に再構成する必要があります。

アプリケーションプロトコルと多くのオプションを定義するにはさまざまな方法がありますので、任意のものを示します。IDとプリロードされたメッセージのテキスト説明(該当する場合) )であり、両方とも不特定の数値変数である。たとえば、リトルエンディアンの4バイトの符号なし整数を選択できます。

この形式のメッセージは、"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. 

は、サーバーとクライアントでこのアプリケーションプロトコルを実装することであるとすれば完了です。

また、クライアントまたはサーバーがprototolに準拠していない場合の対処方法も決める必要があります。たとえば、解析できないメッセージ、未知のメッセージID、サポートしたくないメッセージの長さ、順序外のメッセージ(IncomingFileの前のFileUpload)、またはメッセージサーバが受け入れると言ったより大きいファイルをアップロードするか、または無効な拡張子のように、以前に送信されたメッセージに従ってください。また、「確認応答」や応答メッセージについて考える必要があります。たとえば、サーバーがクライアントに「OK、次のメッセージを送信する」のように伝える必要があります。

全体として、非常にの広い質問ですが、簡単には回答できません。私はあなたの質問への私のコメントでそれを取り除こうとしました。だからここにあなたの答えがあります。

詳細については、Giorgi(全ガイドを必ずお読みください)とStephen Cleary's blogとリンクされているBeej's Guide to Network Programmingなど、ウェブ上でご覧いただけます。

  • が示唆されているように、他の答えに

  • をアプリケーションプロトコルを定義し、部分的な読み取りを処理/読み込み部分の取り扱いについて

を書き込みます:

4

基本的に私は、主に次の2つのことが必要だと思います(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パラメータに指定されているようできるだけ多くのバイトを読んだことがあるために保証されます。したがって、代わりにそのような関数を使用して、目的のアプリケーションプロトコルを実装することができます。

、このようなアプリケーションプロトコルに関するいくつかの関連情報あなたは、これは、サーバーがファイルの長さの制限やファイルの拡張子を送ることができるか、たとえばある[OK]を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

Beejのガイドにリンクするためのupvoteを持っています。ネットワークプログラミングに遠慮なく関心を持つ人でも、少なくとも一度はそのガイドを読むべきです。 – CodeCaster

+0

@コードキャスター:はい、本当にありがとうございます。そのガイドには有用な情報が含まれています。 OPは部分的な送受信を処理する必要があり、あなたの提案やTLVなどのプロトコルについて考える必要があります。 –

+0

私が提案するプロトコル_is TLV、AFAIK。 :-) – CodeCaster