iTop-4412关于linux的网络通信套字节UDP的笔记和代码理解,不会让你失望

首先需要在Ubuntux86上运行服务器程序,然后在开发板上运行客户端来实现。
下面分别将x86服务器程序与开发板客户端程序做一下代码原理笔记,方便查阅复习(这部分的代码个那我之前写的一篇TCP文章里的部分原理相识,不理解的可以回头看一下TCP那篇文章):
1、服务器端程序代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
	int n;
	char recvline[1024] = {0};

	int sockfd;
	struct sockaddr_in servaddr;

	/* 创建一个UDP连接的socket */
	//socket为创建一个通信端点,返回一个描述符
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

	/* 变量servaddr清零 */
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;//使用IPv4协议
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//允许任何地址
	servaddr.sin_port = htons(50001);//设置端口号,要与客户端程序一致

	/* 绑定servaddr到创建的socket上 */
	bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	/* 接收客户端发送的数据 */
	recvfrom(sockfd, recvline, 1024, 0, NULL, NULL);

	printf("%s\n", recvline);

	/* 关闭socket连接 */
	close(sockfd);
}

以上代码是服务器端的接收代码,下面一起阅读以下,整理一下原理和逻辑。首先是定义了一些变量,有一个接受缓存数组以及接受描述符的int变量和设置通信的结构体。然后就是跟TCP通信一样socket(这里就不详细说明该函数原型了,有兴趣的可以查阅我之前的TCP通信的文章)。
接着往后看就是先把设置通信的结构体清零,然后给这个结构体赋值。关于这个结构体的成员定义及值可以查阅TCP通信文章。注意这里有个设置端口号的成员,必须与开发板上的一致才可通信,可自己随意更改。
接下来就是绑定函数bind,这里也不废话了,想具体了解就去看我的TCP通信文章,包括函数原型和参数以及返回值写的很详细。
接着往后看遇到一个recvfrom函数,简单复习一下;函数的原型是:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);recvfrom()和recvmsg()调用用于从套接字接收消息,并且不管套接字是否面向连接,都可以用于接收套接字上的数据。说白了就是一个数据接收函数。
第一个参数:sockfd就是socket返回的描述符。
第二个参数:接收缓存区,也就是这里的recvline数组。
第三个参数:就是这个缓冲区的长度,这里是1024;
第四个参数:一般是0
第五个、第六个参数:一般为NULL
返回值:这些调用返回接收到的字节数,如果发生错误,则返回-1。 当对方执行有序关闭时,返回值将为0。
往后看就是打印这个缓冲区的信息,并且关闭套接字。
2、开发板上客户端程序

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;
	//需要引导用户输入服务器IP
	if(argc != 2)
	{
			printf("usgae: ./client [ip]\n");
			return -1;
	}

	/* 创建一个UDP的socket连接 */
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

	/* 变量servaddr清零 */
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(50001);
	servaddr.sin_addr.s_addr = inet_addr(argv[1]);

	char sendline[100];//发送缓存
	sprintf(sendline, "Hello, world!");//把信息写到发送缓存区里

	/*  发送数据 */
	sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

	/* 关闭socket连接 */
	close(sockfd);

	return 1;
}

下面来阅读客户端的发送代码。大部分的代码跟服务器端的差不多,这里有一个函数复习一下,那就是sendto;函数原型为:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);//sendto函数,功能是向一个已经连接的socket发送数据,如果无错误,返回值为所发送数据的总数,否则返回SOCKET_ERROR。
第一个参数:sockfd就是socket的返回值
第二个参数:发送缓冲区
第三个参数:长度,长度不包含’\0’
第四个参数:flags参数是零个或多个以下标志的按位或。这里是0;
第五个、第六个参数:如果在连接模式套接字上使用sendto(),则忽略参数dest_addr和addrlen(并且当它们不是NULL和0时可能返回错误EISCONN),并且当套接字时返回错误ENOTCONN 实际上没有连接。 否则,目标地址由dest_addr给出,其中addrlen指定其大小。 对于sendmsg(),目标的地址由msg.msg_name给出,其中msg.msg_namelen指定其大小。这里是NULL。
返回值:成功调用后,这些调用将返回发送的字符数。 如果出错,则返回-1,并正确设置errno。
数据发送完毕后关闭套接字。UDP的通信方式没有TCP复杂,但是安全性上不如TCP。代码也比较简单。这两个通信方式的原理大致相同,显示创建套接字,然后绑定结构体,然后就是信息交互,完成后关闭套接字。

送给阅读过这篇文章的人:财富的本性是对外扩张,而不是内斗;但是往往在前进的道路上都死于互掐。
下篇文章见。

发布了6 篇原创文章 · 获赞 3 · 访问量 101

猜你喜欢

转载自blog.csdn.net/weixin_38403894/article/details/105544311