如何连接到具有初始字节的套接字



我发现使用EndAccept传输初始数据是可能的。

这是来自文档:

EndAccept(Byte[],IAsyncResult(

异步接受传入连接尝试并创建处理远程主机通信的新Socket对象。这种方法返回包含传输的初始数据的缓冲区。C#

如何发送此初始字节?BeginConnect没有给我这个选项。我还能用别的方法吗?

使用.NETSocketAPI时,请务必记住,此API不是.NET本机的。它是Windows Winsock 2 API的包装器,该API本身是原始Berkeley套接字API的Windows实现。这意味着在底层网络级别上可能存在.NET API不一定公开的功能。

此外,重要的是要记住,Socket类提供了多种方法来完成相同的任务。特别是,Socket.Connect()方法并不是唯一可用于创建连接的机制。还有一种Socket.ConnectAsync()方法,它使用SocketAsyncEventArgs为套接字操作(包括连接请求(提供状态,并且这种数据结构确实为请求连接的客户端提供了一种方式,以便也提供要发送的数据缓冲区。

即使没有Socket方法,远程端点也可能不会使用.NET的API进行连接请求。其他套接字API,如Winsock 2中的WSAConnect()函数,为客户端提供了一种机制,以包括要与连接请求一起传输的数据缓冲区。

我怀疑你是否会在另一个答案所描述的场景中发现这些数据。即,如果客户端将连接请求与任何实际的发送操作分开,则随后发送的数据将不会包含在连接请求中。这是因为客户端在连接请求完成之前无法在套接字上发送数据,而在服务器调用EndAccept()之前则无法发送数据。与EndAccept()一起交付的任何数据都必须作为原始连接请求的组成部分提供。

同步Socket.Connect()方法没有提供这样做的方法,这是正确的,但还有其他可用的连接机制,包括Socket.ConnectAsync(),以及非.NET套接字API,它们确实允许将数据缓冲区作为连接请求的一部分。这些数据将作为EndAccept()方法调用的一部分由服务器接收。

我相信,如果您使用等待发送初始数据块的两个重载之一调用BeginAccept,那么相应的EndAccept将提供该数据块。如果调用该重载,则意味着在服务器端,接受客户端的API调用直到客户端发送了一些数据才完成。我想这在你的服务器代码中更有效,这样你就不会醒来,直到你接受的客户端有一些有用的数据。这可以节省大规模服务器中的上下文切换,并提高效率。

如果您只是调用BeginAccept的重载,而不是请求等待初始数据,那么相应的EndAccept将不会提供任何初始传输的数据。

这一点在AcceptEx(BeginAccept内部调用的函数(的文档中显而易见,摘录如下:

如果提供了接收缓冲区,则在接受连接并读取数据之前,重叠操作不会完成。

所以你的问题"我如何发送这个初始字节?"的答案从技术上讲就是让客户端"发送"。

最新更新