因此,我可以像为TCP套接字一样为每个客户端创建一个不同的UDP套接字吗?
注意:如果可能,请使用socket
类来解释,而不是UDPClient
类。
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Accept:
case SocketAsyncOperation.Connect:
UDP.Bind(TCP.LocalEndPoint);
代码说明:我以为建立TCP连接(Connect/Accept)后可以在两边(客户机/服务器)绑定一个UDP套接字。对于服务器上只有一个客户机是很好的。对于新客户机,server会引发异常,因为它无法将多个套接字与一个localEndPoint绑定在一起。和客户端可以超过所有可用端口。所以我不能为每个客户端绑定一个UDP套接字到一个不同的localEndPoint。
我知道我可以创建一个唯一的UDP套接字并将接收消息传递给服务器上的相应客户端对象,但这有点麻烦。谢谢!
您可以针对唯一的源ip:port组合运行一个任务。这将允许您轻松地为每个唯一的传入源ip:port组合维护一个状态机。system.io.pipelines
使将其绑定在一起变得非常容易。
首先设置一个类似于TCPListener
的UdpListener
任务,为每个新的ip:port升级一个任务以处理该端口,创建一个管道,并且每个时间的数据都来自该IPEndpoint,将数据放入PipeWriter
static async Task StartUdpListener()
{
// Use a Dictionary to match packets from given connections to give Pipes
ConcurrentDictionary<string, Pipe> connections = new ConcurrentDictionary<string, Pipe>();
var udpServer = new UdpClient(new IPEndPoint(IPAddress.Any, 33000));
while (true)
{
// Wait for some data to arrive
var result = await udpServer.ReceiveAsync();
if(connections.ContainsKey(result.RemoteEndPoint.ToString()))
{
// If we have seen this IPEndpoint before send the traffic to the pipe
// the task associated with that Pipe willpick the traffic up
connections.TryGetValue(result.RemoteEndPoint.ToString(), out var p);
await p.Writer.WriteAsync(result.Buffer);
}
else
{
// If we have not seen it, make the pipe, stick the data in the pipe
// and spin up a task to Read/Process the data
var p = new Pipe();
connections.TryAdd(result.RemoteEndPoint.ToString(), p);
await p.Writer.WriteAsync(result.Buffer);
_ = Task.Run(() => UdpServerClient(result.RemoteEndPoint.ToString(), p));
}
}
}
这是内核在接收到TCPPacket时所做的操作的一个简单视图,它将其粘贴在套接字缓冲区中,供您通过流读取。
UDP服务器客户端
任务如下所示:
static async Task UdpServerClient(string serverName,Pipe p)
{
while (true)
{
var readResult = await p.Reader.ReadAsync();
var message = Encoding.ASCII.GetString(readResult.Buffer.FirstSpan.ToArray());
Console.WriteLine($"Server: {serverName} Received: {message}");
p.Reader.AdvanceTo(readResult.Buffer.End);
}
}
为了完整起见,有几个客户机,它们通常在不同的机器上,但为了简单起见,我们将它们作为任务运行。
static async Task UdpClientClient(string messageToSend)
{
var client = new UdpClient();
client.Connect("127.0.0.1", 33000);
for(var i=0;i<5;i++)
{
var message = ASCIIEncoding.ASCII.GetBytes(messageToSend + " #"+ i.ToString());
await client.SendAsync(message, message.Length);
await Task.Delay(1000);
}
}
}
将它们全部链接在一起:
static async Task Main(string[] args)
{
_ = Task.Run(() => StartUdpListener());
_ = UdpClientClient("hi Server!");
_ = UdpClientClient("I am here server...");
await UdpClientClient("Me too server!");
}
Server: 127.0.0.1:53183 Received: Me too server! #0
Server: 127.0.0.1:53182 Received: I am here server... #0
Server: 127.0.0.1:53181 Received: hi Server! #0
Server: 127.0.0.1:53182 Received: I am here server... #1
Server: 127.0.0.1:53183 Received: Me too server! #1
Server: 127.0.0.1:53181 Received: hi Server! #1
Server: 127.0.0.1:53182 Received: I am here server... #2
Server: 127.0.0.1:53183 Received: Me too server! #2
Server: 127.0.0.1:53181 Received: hi Server! #2
Server: 127.0.0.1:53182 Received: I am here server... #3
Server: 127.0.0.1:53181 Received: hi Server! #3
Server: 127.0.0.1:53183 Received: Me too server! #3
Server: 127.0.0.1:53183 Received: Me too server! #4
Server: 127.0.0.1:53181 Received: hi Server! #4
Server: 127.0.0.1:53182 Received: I am here server... #4
问题内容: 我的MySQL数据库中有这些表: 通用表: Facebook表: 首席表: 基本上,常规表包含一些( 显然 )常规数据。基于generalTable.scenario,您可以在其他两个表中查找更多详细信息,这些表在某些熟悉的列中(例如,expiresAt),而在其他一些列中则不然。 我的问题是,如何仅通过一个查询就可以获取generalTable和正确的明细表的联接数据。 所以,我想这
问题内容: 我们有n个变量,它们没有任何结构。 例如在python中,我可以这样做: 在Java中,我必须这样做: 您知道一种改进此语法的简单方法吗?(想象一下很长的变量名以及很多) 谢谢。 问题答案: 如果您有很多这样的变量,是否考虑过将它们放在集合中,而不是将它们作为单独的变量?此时有多种选择。 如果发现自己经常这样做,则可能要编写辅助方法,可能使用varargs语法。例如: glowcode
问题内容: 我以前用C编写过代码,但是我是Java的新手,我正在为OOP类编写教程,这几乎是我第一次正式学习该语言。 在本教程中,我的教授制作了一个类,该类将用于测试我必须自己做的I / O助手类 (顺便说一句,该教程是(a)可选的,(b)不是用于标记的,所以我是(c)我以前从未使用过Java,而我的许多其他同学都没有使用过Java,所以我落后了)。 无论如何。在他制作的测试类中,他将方法“ ge
我正在使用java。util。ServiceLoader创建轻量级插件框架。 我目前正在努力解决如何拥有多个具有相同FQN的实现类。我想在类路径上拥有同一个插件的两个副本,并且可以访问META-INF/services目录中给出的两个实现类。 以下是一些简单的eclipse项目,它们说明了我的意思:https://docs.google.com/open?id=0B4MxFm-ACB3IUmswN
问题内容: 。 我有下表: 我需要用计算所有行。可能与聚合有关吗? 现在,我按如下操作: 问题答案: 如果您只需要对1的行数进行计数,则可以执行以下操作: 如果要计算 每 行的行数,则需要使用:
问题内容: 我是Swift的新手,我已经遍历了一些教程,其中许多教程使用同一个名称多次定义了一个函数。 我已经习惯了其他编程语言,否则将无法执行此操作。 因此,我检查了官方的Swift手册,还检查了override关键字,以了解可以得到的结果,但是仍然无法理解以下代码: 从我看到的函数tableView设置在第1行和第5行,我注意到的唯一区别是第一个tableView函数返回,而第二个函数返回(U