gpt4 book ai didi

c# - 从服务器广播消息

转载 作者:可可西里 更新时间:2023-11-01 02:34:09 24 4
gpt4 key购买 nike

我正在学习套接字,目前;我正在努力向所有连接的客户端广播消息。

服务器只是用这段代码启动:

public static int Main(String[] args)
{

Thread t1 = new Thread(Test);
t1.Start();


#region Start listening to socket
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

try
{
listener.Bind(localEndPoint);
listener.Listen(100);

Console.WriteLine("[{0}] Server started listening!", DateTime.Now);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
#endregion

Console.WriteLine("\nPress ENTER to continue...");
Console.Read();

return 0;
}

在那里,如果有人发送消息,我会启动 socket 来监听。

如您所见,我有 thread 在那里,我希望该线程不时向所有连接的用户发送一些消息(目前所有时间只有几个字节仅用于测试)。

这是线程中的方法

private static void Test()
{
while (true)
{
for (int i = 0; i < Players.Length; i++)
{
if (Players[i] == null)
continue;

Socket cs = new Socket(Players[i].IPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

cs.Bind(Players[i].IPEndPoint);

byte[] data = Encoding.ASCII.GetBytes("Random data");

cs.Send(data);
}
}
}

此方法仅是最后一次尝试但未成功。问题是它给我的错误是:

socket is reference of null.

在这种情况下,但无论如何我都无法向每个客户发送消息。

以下是我如何跟踪客户端与服务器的连接。

case "0": // Client tries to connect to server

if (nClients >= MAX_PLAYERS)
{
Send(handler, "Too many players. Try again later.");
return;
}

for (int i = 0; i < MAX_PLAYERS; i++)
{
if(Players[i] == null)
{
Players[i] = new Client();
Players[i].Name = parts[1].ToString();
Players[i].IPEndPoint = handler.RemoteEndPoint as IPEndPoint;

Send(handler, String.Format("1|{0}", i));
Console.WriteLine("[{0}] Succesfully registered client ID: {1}, NAME: {2}!", DateTime.Now, i, parts[1].ToString());
i = MAX_PLAYERS;
nClients++;
}
}
break;

这只是我的方法中专注于处理连接消息的代码的一部分:

private static void HandleMessages(string message, Socket handler)

我从这里调用它:

public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;

// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);

if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));

// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
string message = content.Remove(content.Length - 5, 5);
HandleMessages(message, handler);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}

最佳答案

虽然我不能为您编写所有代码,但我会教您一些模式,让您走上正轨。

我假设您正在通过 TCP 进行通信。套接字代表一个连接。如果你想发送一些东西,你必须使用相同的 Socket您用于接收的实例。创建一个新套接字和 Bind将用于打开另一个监听端口(此处不适用)。

您可能希望每个连接都有一个对象来跟踪所有相关状态。例如:

class MyConnection {
Socket socket;
Player player;
}

List<MyConnection> 中跟踪该类的实例.然后您可以遍历该列表并使用 socket发送一些东西。


你可以大大简化接受循环。这是一个很好的模式:

while (true) {
var connectionSocket = listeningSocket.Accept();
Task.Run(() => ProcessConnection(connectionSocket));
}

Microsoft 示例代码中的所有异步内容都没有用。只有一个接受线程。异步用于保存线程。保存一个线程没有帮助。此外,阻塞事件完全抵消了异步的好处。

如果连接的客户端数量较少(<100)和/或如果您关心简单的代码,您可以简单地摆脱所有异步 IO 并使用同步 IO(无 Begin/End)。

或者,您可以使用基于任务的套接字包装器或使用 NetworkStream它具有基于任务的方法。然后您可以使用 await .这也摆脱了那些使编写简单逻辑变得非常困难的回调。

如果这还不足以帮助您,我们可以在评论中工作。

关于c# - 从服务器广播消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54103371/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com