2016-01-13 17 views
6

Tôi đang sử dụng ổ cắm trong C# để gửi dữ liệu từ máy chủ đến máy khách. Trong thực tế, tôi đã tạo ra một capturer mà capin kinect dòng từ 3 máy khác nhau. Tôi muốn tạo ra một máy chủ và giao tiếp khách hàng để gửi tín hiệu từ máy chủ đến các thiết bị còn lại để bắt đầu và dừng quá trình ghi âm. Tôi muốn với nhấp chuột trái để gửi tin nhắn để bắt đầu ghi âm và nhấp chuột phải để dừng ghi âm. Mã của tôi là như sau:Gửi cờ từ máy chủ đến khách hàng bằng các sự kiện chuột #

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()); 
    } 
} 

Làm cách nào để phân tích cờ vào máy chủ, để gửi giá trị đó đến khách hàng? Có thể thay đổi ở đây kiểu tĩnh của các chức năng máy chủ không? Vì nó bây giờ mã bắt đầu máy chủ mà chỉ gửi chuỗi "bắt đầu" cho khách hàng. Làm thế nào tôi có thể gửi tin nhắn chuỗi của một cờ bool? Vấn đề của tôi nằm trong loại tĩnh của hàm gọi lại của tôi. Có thể thêm làm đối số cho thông điệp chẳng hạn trong AsyncCallBack:

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

Hey, bây giờ bạn đang sử dụng 'Async' khá tốt. ;) tuyệt quá! – Ian

+0

: P Tôi đã có một giáo viên tốt! @Ian là nó khả thi để thêm một đối số bên trong AsyncCallback? –

+0

Không không, tôi nghĩ bạn vừa bắt kịp nhanh. = D – Ian

Trả lời

2

Thứ nhất, về sự kiện MouseClick. Kể từ khi bạn đang gặp độc quyền trình độ chuyên môn cho sự kiện này (có nghĩa là, một cú nhấp chuột trái và một click chuột phải), bạn có thể kết hợp cả hai thành một đơn 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. 
    } 
} 

Và nó sẽ là ok.

Tiếp theo, giải đáp thắc mắc của bạn:

Q: Làm thế nào tôi có thể phân tích cờ vào máy chủ, để gửi giá trị trong khách hàng?

A: trong trường hợp mouseClick1 của bạn, chỉ cần sử dụng sync gửi mà bạn làm trong accept callback của bạn, thay đổi msg với cái gì khác (nói 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: Có thể thay đổi ở đây loại static chức năng của máy chủ?

A: Vâng, chắc chắn! nó là windows form, bạn không cần sử dụng static loại nào cả! Không giống như Console App trong câu hỏi trước của bạn. Tôi sẽ thậm chí đề nghị bạn làm gì static bất cứ khi nào có thể

Q: Như bây giờ là mã bắt đầu máy chủ mà chỉ gửi chuỗi "bắt đầu" vào clients. Làm cách nào để gửi thông báo string của một lá cờ bool ?

A: vì bạn sử dụng ổ cắm, bạn không thể gửi cờ bool để nói. Bạn sẽ gửi byte[]. Nhưng bạn luôn có thể kiểm tra trong thực hiện của khách hàng . Nếu byte[] có giá trị nhất định, chỉ cần đổi thành bool. Ví dụ: hãy xem xét gửi chỉ 1 hoặc 0 từ máy chủ của bạn.Sau đó, trong khách hàng của bạn endReceiveCallback, bạn có thể chỉ cần kiểm tra các data tới và xem nếu nó là 1 sau đó nó là true, và nếu nó là 0 sau đó nó là false

Q: Vấn đề của tôi nằm trong các loại static của tôi chức năng gọi lại. Là nó thể thêm như một tham số được thông báo ví dụ như trong AsyncCallBack

A: đây là winform, bạn có thể thoát khỏi tất cả static var! Và có, chỉ cần chuyển nó như là thay thế của null trong Begincallback của bạn. Sau đó, bạn cũng vượt qua đối tượng.

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

Sau đó, trong acceptCallback của bạn, hãy đối tượng của bạn bằng cách sử dụng các IAsyncResult.AsyncState

+1

Dù sao, hãy cố gắng tìm ra bằng cách sử dụng câu trả lời tôi đã đăng. ;) nó không phải là khó, thực sự. Xin lỗi, tôi có thể cần gỡ lỗi mã của tôi trước, có thể không phản hồi nhanh các nhận xét tiếp theo của bạn. Tôi hiện có vấn đề này: http://stackoverflow.com/questions/34767669/same-code-but-different-results-in-windows-form-and-in-windows-service-during-s – Ian

+0

Có, tuy nhiên khách hàng dường như chấp nhận một tin nhắn đúng lúc. Tôi có nghĩa là nếu nó thay đổi với nhấp chuột thứ hai. –

+0

Tôi khởi tạo một biến tin nhắn và trong chấp nhận gọi lại, tôi gửi nó cho khách hàng. Hơn nữa tôi có mã foreach bên trong các nút. Chỉ biến khởi tạo được gửi cho máy khách. –

Các vấn đề liên quan