套接字术语——什么是“阻塞”?

4
当谈到C#中的套接字编程时,术语“blocking”是什么意思?
我需要构建一个服务器组件(可能是Windows服务),用于接收数据,进行一些处理并将数据返回给调用者。调用者可以等待回复,但我需要确保多个客户端可以同时调用。
如果客户端1连接,并且我花费10秒钟来处理他们的请求,那么对于2秒钟后呼叫的客户端2,套接字是否会被阻塞?还是该服务将在不同线程上开始处理第二个请求?
总之,我的客户端可以等待响应,但我必须能够同时处理多个请求。

如果你真的需要使用原始套接字,那么网络上有数十个多线程服务器的示例,只需谷歌一下即可。如果你不需要使用原始套接字,则可以看看WCF。 - hyp
6个回答

6

阻塞指的是您发起的调用(发送/接收)不会返回(“阻塞”),直到底层套接字操作完成。

对于读取,这意味着直到接收到一些数据或套接字被关闭为止。对于写入,它意味着缓冲区中的所有数据都已发送。

处理多个客户端时,为每个客户端启动一个新线程/将工作分配给线程池中的线程。

TCP连接的套接字不能共享,因此无论如何每个客户端必须有一个套接字。


0

阻塞调用会使当前执行的线程保持等待状态,直到调用完成。

例如,如果您希望从网络流中读取10个字节,请按以下方式调用Read方法。

byte[] buf = new byte[10];
int bytesRead = stream.Read(buf, 0, buf.Length);

当前正在执行的线程将在读取10个字节(或读取超时已过期)之前阻塞在Read调用上。
有异步变体的Read和Write,以防止阻塞当前线程。这些遵循.NET中标准的APM模式。异步变体避免了必须针对每个客户端处理一个(将被阻塞的)线程,从而增加可扩展性。
阻塞操作通常是发送或接收数据以及建立连接的操作(即侦听新客户端或连接到其他侦听器)。

0

0
回答你的问题,阻塞基本上意味着控制留在一个函数或代码块中(例如C++中的readfile()),直到它返回并且不移动到此代码块后面的代码。这可以是单线程或多线程上下文。虽然在单线程代码中使用阻塞调用基本上是灾难的配方。
解决方案:
为了解决这个问题,在C#中,你可以简单地使用异步方法,例如sockets上的BeginInvoke()和EndInvoke(),这样就不会阻塞你的调用。这被称为异步编程方法。你可以在委托或控件上调用BeginInvoke()和EndInvoke(),具体取决于你遵循哪种异步方法来实现这一点。

0

你可以使用函数 Socket.Select()

Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds)

检查多个套接字的可读性或可写性。优点是简单易行。可以从单个线程中完成,并且可以指定等待时间,无限等待(-1微秒)或特定持续时间。而且您不必使套接字异步(即:保持阻塞状态)。

它还适用于监听套接字。当有连接要接受时,它将报告可写性。通过实验,我可以说它也会报告优雅断开的可读性。

它可能不如异步套接字快。它也不适合检测错误。我没有太多使用第三个参数的经验,因为它无法检测非优雅断开。


-1

每个线程应该使用一个套接字。阻塞套接字(同步)在返回之前等待响应。非阻塞(异步)可以查看是否收到任何数据,如果还没有数据,则立即返回。


-1: 第一句话完全错误(一般建议不要这样做,使用异步操作避免将线程绑定到套接字)。答案的其余部分基本正确但含糊不清("response" 在这里有两个意思:API 返回和来自套接字另一端的数据)。 - Richard
1
我不建议初学者像OP一样从异步操作开始。'您应该为每个线程使用一个套接字' 对于新手来说是完全正确的建议。然而,异步操作并不会“窥探”。它们只是“休眠”,直到操作系统通知套接字上有事件发生。 - jgauffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接