我在c#中使用套接字,以便将数据从服务器发送到客户端计算机。实际上,我创建了一个捕获器,可以捕获来自3种不同机器的kinect流。我想生成服务器和客户端通信,以便将信号从服务器发送到其余设备,以便开始和停止记录过程。我想用鼠标左键发送一条消息以开始记录,而用鼠标右键单击以停止记录。我的代码如下:

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”。如何发送布尔标志的字符串消息?我的问题在于回调函数的静态类型。是否可以在AsyncCallBack中添加消息作为参数:

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

最佳答案

首先,关于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。如何发送stringbool消息
  旗?
  
  答:由于您使用套接字,因此您无法真正发送bool标志,因此
  说话。您将发送byte[]。但是您可以随时签入
  客户实施。如果byte[]具有特定值,则只需
  将其更改为bool。例如,考虑只发送10
  从您的服务器。然后,在您的客户endReceiveCallback中,您可以
  只需检查即将出现的data,看看它是否为1,然后为true
  如果是0,则为false
  
  问:我的问题在于回调函数的static类型。是吗
  可以将消息添加为参数,例如
  AsyncCallBack
  
  答:这是winform,您可以摆脱所有static var!是的,
  只需将其作为替换null Begin中的callback即可。
  然后,您也传递对象。

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

  
  然后在acceptCallback中,使用IAsyncResult.AsyncState

08-25 17:44
查看更多