2016-01-13 51 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()); 
    } 
} 

如何解析標記到服務器,以便在客戶端發送該值?有沒有可能在這裏改變靜態類型的服務器功能?現在,代碼開始向服務器發送字符串「開始」給客戶端。我怎樣才能發送一個布爾標誌的字符串消息?我的問題在於我的回調函數的靜態類型。是否可以添加爲參數的消息,例如在的AsyncCallback:

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

嘿,現在你正在使用'Async'相當不錯。 ;)太棒了! – Ian

+0

:P我有這麼好的老師! @Ian是否可以在AsyncCallback中添加一個參數? –

+0

不,不,我認爲你只是快速捕捉。 = D – Ian

回答

2

首先,關於MouseClick事件。既然你有獨家資格的事件(即,一個左擊另一右鍵),你可以將它們兩者結合成一個單一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. 
    } 
} 

而且這將是確定。

接下來,回答你的問題:

問:我怎樣才能解析標誌到服務器,以發送值 中的客戶端?

答:在你的mouseClick1事件,只需使用sync發送,你做你的accept callback,用別的東西改變msg(比如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)); 

問:是否可以在這裏改變static類型的服務器功能?答:是的,絕對是!它是windows form,你根本不需要使用static 類型!與上一個問題中的Console App不同。我會 甚至建議你做什麼static儘可能

問:現在的代碼開始其只發送字符串 「開始」到clients服務器。我怎樣才能發送 標誌的string消息?

答:既然你使用套接字,你真的不能發bool這樣的標誌,所以要 說話。您將發送byte[]。但是您可以隨時登錄您的 客戶端實施。如果byte[]具有一定的價值,只需將 更改爲bool即可。例如,考慮從您的服務器發送10 。然後在客戶端endReceiveCallback,你可以 簡單地檢查data來,看看它是否是1那麼它是true, 如果是0那麼false

問:我的問題在於static類型的我回調函數。它是 可能在 AsyncCallBack

一個添加爲參數的消息,例如:這是winform,你可以擺脫所有static變種!是的, 只是通過它作爲替換您的Begincallback中的null。 然後你也傳遞對象。

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

然後在你的acceptCallback,把你的對象使用IAsyncResult.AsyncState

+1

無論如何,試着找出我使用我發佈的答案。 ;)這並不難,真的。對不起,我可能需要先調試我的代碼,可能不會對您的後續評論做出快速響應。我目前有這個問題:http://stackoverflow.com/questions/34767669/same-code-but-different-results-in-windows-form-and-in-windows-service-during-s – Ian

+0

是的,但客戶端似乎在接受一條消息。我的意思是如果它通過第二次點擊發生變化。 –

+0

我初始化一個消息變量,並在接受回調函數中發送給客戶端。此外,我有按鈕內的foreach代碼。只有初始化變量發送給客戶端。 –

相關問題