2016-01-13 23 views
6

サーバーからクライアントマシンにデータを送信するために、C#でソケットを使用しています。実際には私は3つの異なるマシンからkinectストリームをキャプテンキャプチャを作成しました。私は、記録プロセスを開始して停止するためにサーバーから残りのデバイスに信号を送信するために、サーバーとクライアントの通信を生成したいと考えています。録音を開始するには左クリックし、録音を停止するには右クリックしてください。私のコードは次の通りです:C#マウスイベントを使用してサーバーからクライアントにフラグを送信する

public Form1() 
{ 
    InitializeComponent(); 
    this.MouseClick += mouseClick1; 


    Thread thread = new Thread(() => StartServer(message)); 
    thread.Start(); // server is begining 
} 

private void mouseClick1(object sender, MouseEventArgs e) 
{ 

    if (e.Button == MouseButtons.Left) 
    { 
     message = "start"; 
     try 
     { 
       obj = new Capturer(dirPath + name + "_" + surname, 20); 
     } 
     catch (Exception e1) 
     { 
      Console.WriteLine("The process failed: {0}", e1.ToString()); 
     } 
     if (clientSockets.Count > 0) 
     { 
      Thread.Sleep(10); 
      foreach (Socket socket1 in clientSockets) 
       socket1.Send(Encoding.ASCII.GetBytes(message)); //send everything to all clients as bytes 
     } 
     else 
     { 

      serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client 
     } 

    } 
    else if (e.Button == MouseButtons.Right) 
    { 
     message = "stop"; 
     obj.flag2 = true; 

     if (clientSockets.Count > 0) 
     { 
      Thread.Sleep(10); 
      foreach (Socket socket1 in clientSockets) 
       socket1.Send(Encoding.ASCII.GetBytes(message)); //send everything to all clients as bytes 
     } 
     else 
     { 

      serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client 
     } 
    } 
} 

public void StartServer(String message) { 

    serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT_NO)); 
    serverSocket.Listen(4); //the maximum pending client, define as you wish 
    serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); 
    string result = ""; 
    do 
    { 
     result ="asdf"; 
    } while (result.ToLower().Trim() != "exit"); 
} 
private const int BUFFER_SIZE = 4096; 
private static byte[] buffer = new byte[BUFFER_SIZE]; //buffer size is limited to BUFFER_SIZE per message 
private static List<Socket> clientSockets = new List<Socket>(); //may be needed by you 
private static void acceptCallback(IAsyncResult result) 
{ //if the buffer is old, then there might already be something there... 
    Socket socket = null; 
    try 
    { 

     socket = serverSocket.EndAccept(result); // The objectDisposedException will come here... thus, it is to be expected! 
     //Do something as you see it needs on client acceptance 
     clientSockets.Add(socket); 
     socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket); 


     string msg = "start"; 
     //socket.Send(Encoding.ASCII.GetBytes(msg)); 

     if (clientSockets.Count > 0) 
     { 
      Thread.Sleep(10); 
      foreach (Socket socket1 in clientSockets) 
       socket1.Send(Encoding.ASCII.GetBytes(msg)); //send everything to all clients as bytes 
     } 
     else 
     { 

      serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client 
     } 
    } 
    catch (Exception e) 
    { // this exception will happen when "this" is be disposed...   
     //Do something here    
     Console.WriteLine(e.ToString()); 
    } 
} 

const int MAX_RECEIVE_ATTEMPT = 10; 
static int receiveAttempt = 0; //this is not fool proof, obviously, since actually you must have multiple of this for multiple clients, but for the sake of simplicity I put this 
private static void receiveCallback(IAsyncResult result) 
{ 
    Socket socket = null; 
    try 
    { 
     socket = (Socket)result.AsyncState; //this is to get the sender 
     if (socket.Connected) 
     { //simple checking 
      int received = socket.EndReceive(result); 
      if (received > 0) 
      { 
       byte[] data = new byte[received]; //the data is in the byte[] format, not string! 
       Buffer.BlockCopy(buffer, 0, data, 0, data.Length); //There are several way to do this according to http://stackoverflow.com/questions/5099604/any-faster-way-of-copying-arrays-in-c in general, System.Buffer.memcpyimpl is the fastest 
       //DO SOMETHING ON THE DATA int byte[]!! Yihaa!! 
       Console.WriteLine(Encoding.UTF8.GetString(data)); //Here I just print it, but you need to do something else      

       //Message retrieval part 
       //Suppose you only want to declare that you receive data from a client to that client 
       string msg = "I receive your message on: " + DateTime.Now; 
       socket.Send(Encoding.ASCII.GetBytes(msg)); //Note that you actually send data in byte[] 
       Console.WriteLine("I sent this message to the client: " + msg); 

       receiveAttempt = 0; //reset receive attempt 
       //socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket); //repeat beginReceive 
      } 
      else if (receiveAttempt < MAX_RECEIVE_ATTEMPT) 
      { //fail but not exceeding max attempt, repeats 
       ++receiveAttempt; //increase receive attempt; 
       socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket); //repeat beginReceive 
      } 
      else 
      { //completely fails! 
       Console.WriteLine("receiveCallback fails!"); //don't repeat beginReceive 
       receiveAttempt = 0; //reset this for the next connection 
      } 
     } 
    } 
    catch (Exception e) 
    { // this exception will happen when "this" is be disposed... 
     Console.WriteLine("receiveCallback fails with exception! " + e.ToString()); 
    } 
} 

クライアントでその値を送信するには、どのようにフラグをサーバーに解析できますか?静的型のサーバ関数をここで変更することは可能ですか?今のように、コードはサーバーを起動し、文字列 "start"をクライアントに送信します。 boolフラグの文字列メッセージを送信するにはどうすればよいですか?私の問題は、私のコールバック関数の静的型にあります。それは、引数としてAsyncCallBackの例のためのメッセージを追加することが可能である:

まず
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); 
+0

を使用して、オブジェクトを取ります。 ;) すばらしいです! – Ian

+0

:P私はそのような良い先生がいました! @Ianは、AsyncCallbackの内部に引数を追加するのは可能でしょうか? –

+0

いいえ、私はあなたが速く追いついていると思います。 = D – Ian

答えて

2

MouseClickイベントについて。あなたは(つまり、1左クリックし、別の右クリックで)イベントの排他的資格を持っているので、あなたは、単一のevent

public Form1() 
{ 
    InitializeComponent(); 
    this.MouseClick += mouseClick1; //one event is enough 

    Thread thread = new Thread(() => StartServer(message)); 
    thread.Start(); // server is begining 
} 

private void mouseClick1(object sender, MouseEventArgs e) 
{ 
    if (e.Button == MouseButtons.Left) 
    { 
     try 
     { 
      obj = new Capturer(dirPath + name + "_" + surname, 20); //captures the kinect streams 
     } 
     catch (Exception e1) 
     { 
      Console.WriteLine("The process failed: {0}", e1.ToString()); 
     } 
    } 
    else if (e.Button == MouseButtons.Right) 
    { 
     obj.flag2 = true; // flag that handle the recording, true value stops the recording, possible I want that value to be send to the client in order the same thing happen. 
    } 
} 

にそれらの両方を組み合わせることができそして、OKになるだろう。

次は、あなたの質問に答える:

Q:どのように私はクライアントにその値 を送信するために、サーバーにフラグを解析することができますか?

A:あなたのmouseClick1イベントでは、単に何か他のもの(byte[] val = new byte[] { 1 };言う)

foreach (Socket socket1 in clientSockets) //Do this in your `if (e.Button == Mouse.Left and Mouse.Right) blocks 
    socket1.Send(Encoding.ASCII.GetBytes(msg)); 

Qでmsgを変更、ごaccept callbackにあなたがsyncセンドを使用します。それはここstaticタイプを変更することは可能ですのサーバー機能の?

A:はい、間違いなく! windows formの場合、static タイプを使用する必要はありません。前の質問のConsole Appとは異なります。私は も、あなたは何もstatic可能な限り

Qをしないことをお勧めします:それはコードは今あるので単なる文字列 がclientsに「スタート」送信サーバーを開始します。 bool フラグのstringメッセージを送信するにはどうすればよいですか?

A:ソケットを使用しているため、実際にboolフラグを送信して と発言することはできません。 byte[]を送信します。ただし、お客様の クライアント実装をいつでもチェックインできます。 byte[]がある値の場合は、 をboolに変更します。たとえば、サーバから1または0を送信することを検討してください。次に、あなたのクライアントendReceiveCallbackに、あなたは 単にdataが来てチェックし、それが1であるかどうかを見ることができ、それは、trueある 、それが0であれば、それはfalse

Qである:私の問題は私のstaticタイプでありますコールバック関数。 AsyncCallBack

Aにたとえば、引数としてメッセージを追加することは可能です :これはwinformで、あなたはすべてのstatic VARを取り除くことができます!はい、 をnullの代わりにそのままBegincallbackに渡してください。 また、オブジェクトも渡します。

//Change null with something else 
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), myobj); 

は、その後、あなたのacceptCallbackで、ねえ、今はかなりよく `Async`を使用しているIAsyncResult.AsyncState

+1

とにかく、私が投稿した答えを使ってそれを理解しようとする。 ;)それは本当に難しいことではありません。申し訳ありませんが、最初にコードをデバッグする必要があり、後のコメントにすばやく反応しない可能性があります。私は現在この問題があります:http://stackoverflow.com/questions/34767669/same-code-but-different-results-in-windows-form-and-in-windows-service-during-s – Ian

+0

はい、ただしクライアント時間に1つのメッセージを受け入れるようです。 2回目のクリックでそれが変更されなければ意味があります。 –

+0

私はメッセージ変数を初期化し、受け入れコールバックでクライアントに送信します。さらに、私はボタン内にforeachコードを持っています。 initialize変数のみがクライアントに送信されます。 –

関連する問題