我在 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”。如何发送 bool 标志的字符串消息?我的问题在于回调函数的静态类型。是否可以将消息作为参数添加到 AsyncCallBack 中:
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null);
最佳答案
首先,关于MouseClick
事件。由于您对事件具有排他性资格(即一次左键单击和另一次右键单击),您可以将它们组合成一个事件
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.
}
}
一切都会好起来的。
接下来,回答您的问题:
Q: How can I parse the flag into the server, in order to send that value in the clients?
A: in your
mouseClick1
event, simply usesync
send which you do in youraccept callback
, change themsg
with something else (saybyte[] 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: Is it possible to change here the
static
type of server functions?A: Yes, definitely! it is
windows form
, you do not need to usestatic
type at all! Unlike theConsole App
in your previous question. I would even suggest you to make nothingstatic
whenever possibleQ: As it is now the code begin the server which send just the string "start" to the
clients
. How can I send thestring
message of abool
flag?A: since you use socket, you cannot really send
bool
flag so to speak. You will sendbyte[]
. But you can always check in your client implementation. If thebyte[]
is of certain value, simply change it tobool
. For instance, consider of sending just1
or0
from your server. Then in your clientendReceiveCallback
, you could simply check thedata
coming and see if it is1
then it istrue
, and if it is0
then it isfalse
Q: My issue lies in the
static
type of my callback functions. Is it possible to add as an argument the message for example in theAsyncCallBack
A: this is
winform
, you could get rid of allstatic
var! And yes, just pass it as replacement of thenull
in yourBegin
callback
. Then you pass the object too.//Change null with something else serverSocket.BeginAccept(new AsyncCallback(acceptCallback), myobj);
Then in your
acceptCallback
, take your object by using theIAsyncResult.AsyncState
关于c# - 使用 C# 鼠标事件从服务器向客户端发送标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34767502/