举例说明C语言中recv 函数的用法

873 阅读6分钟

像许多套接字编程函数一样,"recv() "在C语言编程中是独特的,并且易于使用。recv是一个从注重链接的或异步的套接字中读取传入信息的方法。在利用基于连接的协议调用recv之前,端点,即套接字,应该被链接。在利用无链接协议调用recv之前,端口或套接字应该被绑住。因此,在今天的文章中,我们将讨论在C语言编程中使用 "recv() "函数从一个特定的IP地址获取数据。为此,我们一直在利用Ubuntu 20.04系统。所以,让我们从新开始。

让我们从打开终端开始。这是在Ubuntu 20.04系统的桌面屏幕上通过简单的快捷键 "Ctrl+Alt+T "完成的。你的shell应用程序将在使用该快捷方式的片刻内启动。在走向编码之前,我们要做的第一件事是创建一个C类文件的新文档,即使用C类扩展名。这可以通过在刚刚打开的系统外壳中使用 "触摸 "指令来实现。它将在我们的系统中被创建,并在一些内置的编辑器如text、vim或nano中打开。要在nano编辑器中打开它,使用 "nano "关键字和文件名,如图所示。

例子1:

让我们看看我们的第一个例子,演示C语言的recv()函数在程序中的使用和工作。所以,我们已经开始包括头文件库,即stdio.h、string.h、sys/types.h、sys/socket.h、netinet/in.h。这里是我们代码中的main()和原始函数的执行。在我们的代码中没有用户定义的函数。我们在main()方法中开始声明整数类型的变量 "s1 "和 "bcount"。结构类型变量 "add "已经用套接字库的关键字 "sockaddr_in "构建。这将被声明为在其中添加一个socket的地址。字符型数组变量 "b "已被声明为 "512"。socket()方法被castoff以在变量 "s1 "中生成一个新的socket。

socket函数需要两个参数,"PF_INET "和 "SOCK_STREAM"。PF_INET "参数是指互联网的协议族格式,即TCP、IP。下一个参数 "SOCK_STREAM "指的是TCP,一种基于链接的协议。当两个端点连接并相互监听时,它就会被使用。我们利用结构对象 "add "来设置特定协议的套接字地址族,即AF_INET。这显示了有关套接字地址的信息。

同样的对象 "add "被用来通过 "htons "函数来设置套接字端口号。htons函数是一种利用端口号的转换方法,即从主机字节格式转换为网络字节格式。inet_aton()函数在这里是为了获得套接字的IP地址,将其转换为网络地址的标准格式,并使用 "add "对象将其保存到 "sin_addr "内置。现在,connect()函数用于通过其地址,即 "add "在TCP流套接字 "s1 "和外部套接字/服务器之间建立连接。现在利用 "recv "函数从连接的服务器获取数据,并将其保存到缓冲区 "b "中。这个缓冲区的大小是通过 "sizeof() "函数获得的,并保存在变量 "bcount "中。printf语句将通过bcount变量向我们显示缓冲区内的确切数据字节数。代码到此结束。

该程序已先用 "gcc "编译器进行了编译。

代码执行后,我们得到以下结果,显示收到了1个字节的数据。

例子2:

让我们再举一个例子,从外部端点接收数据。所以,我们在代码中加入了一些头文件来开始我们的代码。我们已经定义了将被接收的每个块的大小。timeout_recv()函数的声明在这里接受2个参数。

main()函数从变量 "sockdesc "开始,用于获取响应。套接字的地址将被存储在变量 "server "中。声明了字符类型指针 "msg "和一个大小为2000的数组 "server_reply"。我们已经创建了一个TCP协议的套接字,并将响应保存在 "sockdesc "变量中。如果套接字没有创建成功,printf语句将显示我们无法做到这一点。我们已经提供了服务器的IP地址、地址族和端口号。这里利用connect()函数来链接到使用套接字的服务器。如果连接在任何层面上都失败了,将显示连接错误信息。如果套接字使用IP地址和端口号成功连接到给定的服务器,它将显示成功信息,即连接到服务器。msg "变量存储了关于服务器的信息,"if "子句用于检查数据是否没有成功传输。如果是这样,它将在shell上显示一个 "数据发送失败 "的消息。

如果数据传输成功,puts函数将显示一个成功信息。这里调用timeout_recv()消息是为了检查非阻塞套接字的超时情况。超时值4已经与 "sockdesc "套接字变量一起被传递。从这个函数收到的超时值将被保存在 "tr "cv "变量中,并使用printf子句在shell上显示。

在timeout_recv()函数中或多或少地说明了可变性,即srecv、tsize、start、now、time diff和数组 "c"。c "数组用于将数据保存为512块。fcntl()函数用于使套接字无阻塞。我们已经用 "gettimeofday "函数得到了开始时间。时间差将被计算出来。如果套接字接收到一些数据,并且计算出的时间差比main()函数传递的超时时间更重要,它将中断循环。否则,它将检查计算出的时间差是否是main()函数传递的超时的2倍。如果条件得到满足,"if "语句就会中断。数组 "c "将被清空,如果没有收到任何数据,它将睡眠0.1秒。如果收到数据,它将计算总大小,并在计算开始时间的同时分块打印出数据。最后,它将返回收到的数据的总大小。

该代码首先使用 "gcc "内置命令进行编译。

之后,用"./a.out "指令执行该程序。首先,套接字成功连接到服务器,数据被成功发送。使用 "recv "功能收到的数据已在下面的图片中展示。

收到的数据的当前日期和时间被显示在shell上。收到的数据的总大小也被显示出来了。

总结

这篇文章涵盖了所有关于在套接字编程中使用C语言的recv()函数的小细节,使我们的用户更容易理解。我们试图涵盖简单的例子以使其成为可能。因此,这篇文章对于每一个在 "recv() "函数使用方面寻求帮助的C语言用户来说都是一个收获。