在侦听套接字上接受侦听套接字上的连接(并且不再侦听)?
我正在使用 ICS (TWSocket) 库在 Delphi 6 Pro 中进行套接字编程。我知道我的问题可能看起来很复杂或尴尬,但让我解释一下我的应用程序需求,以便您理解为什么我想做一些违反侦听套接字使用的常规约定的事情,即将传入连接分拆到新套接字由 Accept 方法返回并继续侦听当前设置端口上的新连接。
在我的应用程序中,我接受来自 Skype 的连接,以发送和接收与活动 Skype 通话相关的音频缓冲区。问题是,当 Skype 连接时,没有握手、识别或身份验证来让我知道连接的 CALL ID。由于 Skype 可以一起进行电话会议,因此一次可以有多个正在进行的通话。但是,我需要知道哪些套接字连接属于哪个 CALL ID。
由于连接是如上所述的“盲”连接,因此我可以可靠地将 Skype 套接字连接映射到 CALL ID 的唯一方法是仔细控制我侦听的端口号。然后,当我告诉 Skype 将给定 CALL ID 的音频连接到特定端口号时,我知道该套接字上的连接属于该 Skype CALL ID。例如:
- 查找可用的端口号 iPortNumber。
- 将我的套接字设置为侦听 iPortNumber
- 告诉 Skype 将 CALL ID iCallID 连接到端口号 iPortNumber
- 当我收到 SessionAvailable 事件时,我知道传入的消息Skype 连接用于 CALL ID iCallID。
对我需要处理的每个呼叫 ID 进行冲洗和重复。我知道这意味着我最终可能会占用一些额外的端口,但由于同时进行的 Skype 通话数量总是很少,我不认为这是一个问题。我遇到的困难是拥有一个侦听套接字的标准约定,当新连接进入时,该侦听套接字会使用 Accept 分离出一个新套接字。
我想在侦听套接字(同一套接字)上接受连接 ),然后专门停止监听,而不必关闭连接,因为我不想再接受该端口号上的任何新连接。有办法做到这一点吗?
另一种途径是使用 Accept 返回的新创建的套接字,然后关闭监听套接字,但随后我必须想出一种更复杂的方法来跟踪 Skype CALL ID 的端口号,因为如果我的知识是正确的,Accept 返回的新创建的套接字连接到与侦听套接字不同的端口号上,因此侦听套接字可以继续侦听现有端口号。如果可以的话,我希望避免额外的复杂性和麻烦。
如果有人对如何将我的盲 Skype 连接映射到与其绑定的 Skype CALL ID 有更好的整体想法/范例,请告诉我。另外,我认为这是不可能的,但如果有一种巧妙的方法可以从与我的应用程序连接在同一系统上的进程获取传入套接字连接后面的进程 ID,我想知道。
I am doing socket programming in Delphi 6 Pro using the ICS (TWSocket) library. I know my question may seem either convoluted or awkward, but let me explain my application needs so you understand why I want to do something that goes against the usual convention used with a listening socket, that of spinning off an incoming connection to a new socket returned by the Accept method and continue to listen for new connections on the currently set port.
In my application I accept connections from Skype for sending and receiving audio buffers involved with an active Skype call. The problem is that when Skype connects, there is no handshaking, identification, or authentication that would allow me to know what CALL ID the connection is for. Since Skype can conference calls together, there can be more than one active call at a time. However, I need to know which socket connections belong to which CALL ID.
Since the connection is a "blind" connection as stated above, the only way I can reliably map Skype socket connections to CALL IDs is by controlling carefully the port number I listen on. Then, when I tell Skype to connect the audio for a given CALL ID to a specific port number, I know that a connection coming in on that socket belongs to that Skype CALL ID. For example:
- Find an available port number, iPortNumber.
- Set my socket to listen on iPortNumber
- Tell Skype to connect CALL ID iCallID to PORT number iPortNumber
- When I get the SessionAvailable event, I know the incoming Skype connection is for CALL ID iCallID.
Rinse and repeat for each CALL ID I need to handle. I know this means I could end up chewing up a few extra ports but since the number of simultaneous Skype calls is always small I don't see that as a problem. What I am having difficulty with is the standard convention of having a Listening socket that spins off a new socket using Accept when a new connection comes in.
I want to Accept the connection on the Listening socket (same socket), and then specifically stop listening without having to close the connection since I don't want to accept any new connections on that port number anymore. Is there a way to do this?
An alternative avenue would be to use the newly created socket returned by Accept and then close the Listening socket, but then I have to come up with a more complicated method to track port numbers to Skype CALL IDs because, if I am correct in my knowledge, the newly created socket returned by Accept is connected on a different port number than the Listening socket so the Listening socket can keep listening on the existing port number. I'd like to avoid that extra complexity and hassle if I could.
If anyone has a better overall idea/paradigm on how to map my blind Skype connections to the Skype CALL IDs that are tied to them, please let me know. Also, I don't think it's possible, but if there's a clever way to get the process ID behind an incoming Socket connection from a process connecting on the same system as my app, I'd like to know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一次性监听套接字并不罕见。例如,FTP 协议就使用它们。只需在所需端口上创建一个新的侦听套接字(或者让套接字决定自己可以检索的端口),将其 backlog 设置为 1,然后对其调用一次
accept()
并关闭它。如果accept()
接受客户端连接,它将返回一个新的套接字句柄,您可以使用该句柄与该客户端进行通信。在此期间,您不需要保持侦听套接字处于活动状态。我不知道该操作的 ICS 等效项是什么,但在 Indy 中,有一个 TIdSimpleServer 组件正是用于此目的(顺便说一句,Windows 上的 Skype 使用 Indy)。
One-time listening sockets are not that unusual. The FTP protocol uses them, for instance. Simply create a new listening socket on the desired port (or let the socket decide its own port that you can then retrieve), set its backlog to 1, then call
accept()
on it just once and close it. Ifaccept()
accepts a client connection, it returns a new socket handle that you use to communicate with that client. You don't need to keep the listening socket alive during that time.I don't know what the ICS equivilent of that operation would be, but in Indy there is a
TIdSimpleServer
component for exactly this purpose (incidentally, Skype on Windows uses Indy).