C# socket receive方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# socket receive方法相关的知识,希望对你有一定的参考价值。

C# 中的socket 中的receive方法一般这样使用:socket.Receive(recvBytes, recvBytes.Length, 0); 这句话是什么意思,因为在msdn上只能查到 receive(recvBytes, int32 offset, int32 size, socketflag),为什么查不到receive(recvBytes, int32, int32), 求大神指导!

Receive 方法将数据读入 buffer 参数,并返回成功读取的字节数。 从面向连接的套接字和无连接套接字中都可以调用 Receive。

此重载仅要求您提供接收缓冲区。 缓冲区偏移量的默认值为 0,缓冲区的默认大小为缓冲区参数的长度,而 SocketFlags 的默认值为 None。

如果您使用的是面向连接的协议,则在调用 Receive 之前,必须调用 Connect 以建立远程主机连接,或者调用 Accept 以接受传入的连接。 Receive 方法只读取在 Connect 或 Accept 方法中建立的远程主机发送的数据。 如果您使用的是无连接协议,则您也可以使用ReceiveFrom 方法。 ReceiveFrom 将允许您收到从任何主机传入的数据。

如果没有可读取的数据,则 Receive 方法将一直处于阻止状态,直到数据可用,除非使用 Socket.ReceiveTimeout 设置了超时值。 如果超过超时值,Receive 调用将引发 SocketException。 如果您处于非阻止模式,并且协议堆栈缓冲区中没有可用的数据,则 Receive 方法将立即完成并引发 SocketException。 您可以使用 Available 属性确定是否有数据可以读取。 如果 Available 为非零,请重试接收操作。

如果当前使用的是面向连接的 Socket,那么 Receive 方法将会读取所有可用的数据,直到达到缓冲区的大小为止。 如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。

如果您使用的是无连接 Socket,则 Receive 将从您在 Connect 方法中指定的目标地址处读取第一个排队的数据报。 如果您接收到的数据报大于 buffer 参数的大小,则 buffer 将用消息的第一部分填充,多余的数据都会丢失,并且会引发 SocketException

public static int SendReceiveTest1(Socket server)

    byte[] msg = Encoding.UTF8.GetBytes("This is a test");
    byte[] bytes = new byte[256];
    try 
    
        // Blocks until send returns.
        int i = server.Send(msg);
        Console.WriteLine("Sent 0 bytes.", i);

        // Get reply from the server.
        i = server.Receive(bytes);
        Console.WriteLine(Encoding.UTF8.GetString(bytes));
    
    catch (SocketException e)
    
        Console.WriteLine("0 Error code: 1.", e.Message, e.ErrorCode);
        return (e.ErrorCode);
    
    return 0;
参考技术A 意思是接收Socket数据包 将数据包保存到 recvBytes的byte[]数组中,为了防止溢出 所以要加起点和长度。 通常就是直接用数组长度了,不过socket有个属性可以获取ReceiveLength byte数组初始化的时候直接为ReceiveLength就行了追问

按照msdn上的说法 receive(buffer , int offset, int size, socketFlag),第一个int型是偏移量,第二个是大小,可是在使用的时候是receive(buffer, buffer.length, 0) ,哪道偏移量是buffer数组最后开始, 大小是0? 求指教

参考技术B

我在msdn查的,socket类的receive有好多重载啊

追问

是啊,有很多receive的重载,可是socket.Receive(recvBytes, recvBytes.Length, 0)同这个类型一样的重载没有啊,费解。

追答

Receive Method (array[]()[], Int32,
SocketFlags)
这个不就是吗?SocketFlags是个枚举,可以用0作为输入啊

本回答被提问者采纳

如何中断阻塞调用UDP socket的receive()[重复]

这个问题在这里已有答案:

我有一个UDP服务器监听来自客户端的数据包。

socket = new DatagramSocket(port);

while (isListen) {
    byte[] data = new byte[1024];
    DatagramPacket packet = new DatagramPacket(data, 0, data.length);
    socket.receive(packet);
}

receive()方法将在收到数据包之前永远等待。是否有可能停止等待接收?我可以设置一个boolean isListen来阻止循环。另一方面,如果套接字正在等待,那么如果没有从客户端发送数据包,它将永远等待。

答案

您可以从另一个线程关闭套接字。然后在receive()中阻塞的线程将抛出IOException。

while (isListen) {
    byte[] data = new byte[1024];
    DatagramPacket packet = new DatagramPacket(data, 0, data.length);
    try {
        socket.receive(packet);
    } catch(IOException e) {
        continue;
    }
}

void stopListening() { // Call me from some other thread
    isListen = false;
    socket.close();
}
另一答案

您需要使用setSoTimeout()方法设置套接字超时,并在超过超时时捕获SocketTimeoutExceptionsocket方法抛出的receive()。捕获异常后,您可以继续使用套接字接收数据包。因此,在循环中使用该方法允许您定期(根据超时设置)“中断”receive()方法调用。

请注意,必须在进入阻止操作之前启用超时。

一个例子(w.r.t你的代码):

socket = new DatagramSocket(port);
socket.setSoTimeout(TIMEOUT_IN_MILLIS)

while (isListen) {
    byte[] data = new byte[1024];
    DatagramPacket packet = new DatagramPacket(data, 0, data.length);

    while (true) {
        try {
            socket.receive(packet);
            break;
        } catch (SocketTimeoutException e) {
            if (!isListen) {} // implement your business logic here
        }
    }
    // handle the packet received
}

以上是关于C# socket receive方法的主要内容,如果未能解决你的问题,请参考以下文章

Socket Receive 避免 Blocking

即使在客户端ShutDown()之后,Socket.Receive也会阻塞

C#TCP协议 socket.receive 超时问题

asio::tcp::socket 的 async_read_some 和 async_receive 有啥区别?

如何中断阻塞调用UDP socket的receive()[重复]

python,socket通信编程,文件上传例子