当前位置: 首页 > article >正文

嵌入式入门Day35

网络编程 Day2

  • 套接字socket
  • 基于TCP通信的流程
    • 服务器端
    • 客户端
    • TCP通信API
  • 基于UDP通信的流程
    • 服务器端
    • 客户端
  • 作业

套接字socket

  1. socket套接字本质是一个特殊的文件,在原始的Linux中,它和管道,消息队列,共享内存,信号等一样,都只能进行主机内的通信
  2. 随着历史的发展,有了TCP/IP协议族的出现,使得socket套接字可以通过网卡,与外部主机进行通信
  3. socket函数会生成一个文件描述符,不同主机内的进程都可以对该文件描述符进程读写

在这里插入图片描述

基于TCP通信的流程

在这里插入图片描述

服务器端

  1. socket:创建原始套接字
  2. bind:将原始套接字与主机IP绑定(该服务器的身份,服务器以主机的身份通信)
  3. listen:将原始套接字设置为监听状态
  4. accept:接收客户端的连接,获取客户端信息,并生成新的套接字描述符用于与客户端通信。
  5. 发送信息,接收信息,关闭

客户端

  1. socket:创建套接字
  2. bind(可选):客户端绑定IP和端口号,绑定后客户端将会使用绑定的IP端口号来访问服务器,如果不绑定系统将会自动分配IP和端口号
  3. connect:向服务器发送连接请求
  4. 发送信息,接收信息,关闭

TCP通信API

#include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);
       功能:创建socket套接字描述符
       参数1:
       AF_UNIX,      
       AF_LOCAL:本地通信模式
       AF_INET        IPv4 通信
       AF_INET6       IPv6 通信
       参数2传输层通信协议:
       SOCK_STREAM:TCP通信协议
       SOCK_DGRAM:UDP通信协议
       参数3:如果参数2指定了TCP或者UDP具体通信协议,参数3可以省略,如果没有指定需要加上参数3.
       返回值:成功返回套接字描述符,失败返回-1,并置位错误码。
       eg:socket(AF_INET,SOCK_STREAM,0)
       
        #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
                参数1:套接字描述符
                参数2;
               struct sockaddr_in {
               sa_family_t    sin_family; /* IPV4通信协议 */
               in_port_t      sin_port;   /* 端口号 */
               struct in_addr sin_addr;   /* IP号(IP地址转化的IP号) */
           };
           参数2结构体第三个成员还是结构体如下:
            struct in_addr {
               uint32_t       s_addr;     /* IP地址在网络的形式 */
           };
        参数3:参数2的结构体大小。
        返回值:成功返回0,失败返回-1,并置位错误码。
        
         
        #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int listen(int sockfd, int backlog);
        功能:监听客户端连接请求
        参数1:套接字描述符
        参数2:监听的最大数量是128。
        返回值:成功返回0,失败返回-1,并置位错误码。
    #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        功能:接收连接请求,并记录连接者的信息(阻塞函数)
        参数1:套接字描述符
        参数2:存储连接者的详细信息。
        参数3:参数2的大小。
        返回值:成功返回新的描述符,失败返回-1,并置位错误码。
		int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
	    功能:与服务器建立连接的函数
 		参数1:套接字描述符
 	 	参数2:需要连接的服务器具体信息(IP,端口号,通信域等)
	  	参数3:参数2的大小。
   		返回值:成功返回0,失败返回-1,并置位错误码

基于UDP通信的流程

在这里插入图片描述

服务器端

  1. 创建套接字
  2. 绑定主机IP和端口号
  3. 收发信息

客户端

  1. 创建套接字
  2. 收发信息

作业

使用UDP和connect函数实现一对一通信

//服务器
#include <myhead.h>

#define IP "192.168.209.241"
#define PORT 6666

int main(int argc, const char *argv[])
{
	//创建UDP套接字
	int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == socketfd)
	{
		perror("socket");
		return -1;
	}
	
	//绑定
	struct sockaddr_in server = {
		.sin_family = AF_INET,
		.sin_port = htons(PORT),
		.sin_addr.s_addr = inet_addr(IP)
	};

	if (-1 == bind(socketfd, (struct sockaddr *)&server, sizeof(server)))
	{
		perror("bind");
		return -1;
	}

	//收发信息
	struct sockaddr_in client;
	int client_len = sizeof(client);

	int flag = 1;
	char buff[1024] = "";
	while (1)
	{
		//记录首个发送信息的客户端并连接
		while (flag)
		{
			recvfrom(socketfd,buff,sizeof(buff),0,(struct sockaddr *)&client, &client_len);
			printf("收到来自%s:%d的信息:%s\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port), buff);
			if (-1 == connect(socketfd, (struct sockaddr *)&client, client_len))
			{
				perror("connect");
				return -1;
			}
			flag = 0;
		}
		strcat(buff,"copy");
		send(socketfd, buff, strlen(buff), 0);
		bzero(buff, sizeof(buff));
		recv(socketfd, buff, sizeof(buff), 0);
		printf("收到来自%s:%d的信息:%s\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port), buff);
		bzero(buff, sizeof(buff));
	}

	return 0;
}

//客户端
#include <myhead.h>

#define IP "192.168.209.241"
#define PORT 6666

int main(int argc, const char *argv[])
{
	//创建UDP套接字
	int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (socketfd == -1)
	{
		perror("socket");
		return -1;
	}
	//连接服务器
	struct sockaddr_in server = {
		.sin_family = AF_INET,
		.sin_port = htons(PORT),
		.sin_addr.s_addr = inet_addr(IP)
	};
	
	if (-1 == connect(socketfd, (struct sockaddr *)&server, sizeof(server)))
	{
		perror("connect");
		return -1;
	}

	//收发信息,因为使用了connect连接了服务器,所以可以直接使用send和recv函数直接操作
	char buff[1024] = "";
	while (1)
	{
		fgets(buff, sizeof(buff), stdin);
		buff[strlen(buff)-1] = '\0';
//		sendto(socketfd,buff,sizeof(buff),0,(struct sockaddr *)&server, sizeof(server));
		send(socketfd,buff, strlen(buff),0);
		bzero(buff,sizeof(buff));
//		recvfrom(socketfd,buff,sizeof(buff),0,NULL,NULL);
		recv(socketfd,buff, sizeof(buff), 0);
		printf("收到服务器信息:%s\n", buff);
	}
	return 0;
}


http://www.kler.cn/a/457529.html

相关文章:

  • MySQL的三大日志
  • xml格式化(1):使用python的xml库实现自闭合标签
  • 【Vue】分享一个快速入门的前端框架以及如何搭建
  • 【Rust自学】10.6. 生命周期 Pt.2:生命周期的语法与例子
  • PDF文件提示-文档无法打印-的解决办法
  • 若依中Feign调用的具体使用(若依微服务版自身已集成openfeign依赖,并在此基础上定义了自己的注解)
  • WSL2桥接模式配置(可与外部设备互ping)
  • workman服务端开发模式-应用开发-vue-element-admin封装websocket
  • 139.《python中的正则详解》
  • 解决编译Wireshark4.4.2源码失败的问题
  • Java8-Function的使用之读取文件
  • 【Linux基础】进程(上) —— 概念、状态、优先级与环境变量
  • 前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
  • 使用Quick 录屏为视频生成二维码
  • 企业人工智能平台 (AIaaP) 的全面解读
  • orm01
  • 深度学习:基于MindSpore NLP的数据并行训练
  • 玩转树莓派Pico(20): 迷你气象站6——软件整合改进
  • Unity3D仿星露谷物语开发9之创建农场Scene
  • Facebook广告优化新知:如何使用即时体验
  • C# dynamic 类型详解
  • 鸿蒙next RCP网络请求工具类进阶版来了
  • 【机器学习】Transformer
  • 代码随想录算法训练营第六十天 | 图 | A星算法
  • Bash语言的并发编程
  • 算法排序算法