学习嵌入式第三十四天

文章目录

网络

1.概念

  • 不同主机间的进程间通信
  • IP:确定主机的地址
  • 端口号:用来标识一个网络通信的进程

2.函数接口

  • socket

    tex 复制代码
    原型:int socket(int domain, int type, int protocol);
    功能:建立通信的一端
    参数:
    	domain:通信的范围,指定网络类型
    	type:套接字类型,指定通信语义
    		SOCK_STREAM		//流式套接字
    		SOCK_DGRAM		//数据报套接字
    	protocol:协议
    返回值:
    	成功返回文件描述符
    	失败返回-1
    Name                 Purpose                           AF_UNIX, AF_LOCAL   Local communication              
    AF_INET             IPv4 Internet protocols         
    AF_INET6            IPv6 Internet protocols         
    AF_IPX              IPX - Novell protocols
    AF_NETLINK          Kernel user interface device  
    AF_X25              ITU-T X.25 / ISO-8208 protocol 
    AF_AX25             Amateur radio AX.25 protocol
    AF_ATMPVC           Access to raw ATM PVCs
    AF_APPLETALK        AppleTalk                    
    AF_PACKET           Low level packet interface           AF_ALG              Interface to kernel crypto API
  • connect

    tex 复制代码
    原型:int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    功能:通过socket连接到指定的地址上
    参数:
    	sockfd:socket函数返回的文件描述符
    	addr:网络中一个进程对应的地址
    	addrlen:说明第二个参数的地址类型的大小
    返回值:
    	成功返回0
    	失败返回-1
    不同的通信域有不同的结构体
    IPv4:
    struct sockaddr_in {
                   sa_family_t    sin_family; /* address family: AF_INET */
                   in_port_t      sin_port;   /* port in network byte order */
                   struct in_addr sin_addr;   /* internet address */
               };
    
               /* Internet address. */
    struct in_addr {
    				uint32_t       s_addr;     /* address in network byte order */
        		};
  • inet_addr

    tex 复制代码
    原型:in_addr_t inet_addr(const char *cp);
    功能:
    参数:
    	cp:表示要用的ip地址的字符串
    返回值;
    	成功返回网络字节序形式的ip地址的32位数值
  • bind

    tex 复制代码
    原型:int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);、
    功能:给socket端口号绑定一个地址信息
    参数:
    	sockfd:socket函数返回的文件描述符
    	addr:网络中一个进程对应的地址
    	addrlen:说明第二个参数的地址类型的大小
    返回值:
    	成功返回0
    	失败返回-1
  • listen

    tex 复制代码
    原型:int listen(int sockfd, int backlog);
    功能:将socketfd对应的socket设置为监听套接字
    参数:
    	sockfd		sockfd的fd
    	backlog		等待队列的长度
    返回值:
    	成功返回0
    	失败返回-1
  • accept

    tex 复制代码
    原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    功能:从监听的socket中提取连接请求,完成三次握手并连接
    参数:
    	sockfd:监听的socket的fd
    	addr:存放客户端的地址信息
    	addrlen:值结果参数
    			必须初始化位addr对应的socket大小
    返回值:
    	成功返回已经连接的新socket的fd
    	失败返回-1

3.主要协议

1.TCP

  1. 特点
    1. 面向连接,即在进行通信之前,必须建立好一条逻辑上的通路
    2. 提供可靠传输,即无丢失,无失序,无差错,无重复
  2. 建立连接流程(三次握手)
    1. 向服务器请求连接
    2. 回复请求是否可以连接
    3. 向服务器回复连接建立成功
  3. 应用场景
    • 电子邮件收发,web浏览
    • 文件的传输
    • 远程登陆和服务器的管理

2.UDP

  1. 特点
    1. 不提供可靠传输
    2. 在数据发送时,不需要建立连接
  2. 应用场景
    • 小数据,但是对速度要求较高,实时性要求较高
    • 广播,组播
    • 无线网的传输

习题

1.客户端向服务器发送一条消息,客户端回复收到

c 复制代码
#include<stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<netinet/ip.h>
#include<unistd.h>
#include<stdint.h>
#include<string.h>
#include<strings.h>

int main(void){

    int fd;
    char tmp[256] = {0};

    fd = socket(AF_INET, SOCK_STREAM, 0);

    if (fd < 0) {

        perror("socket");
        return 1;
    }
    
    printf("fd = %d\n", fd);

    struct sockaddr_in seraddr;

    bzero(&seraddr,sizeof(seraddr));
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(50000);
    seraddr.sin_addr.s_addr = inet_addr("192.168.0.182");

    if(bind(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){

        perror("fail to connect");
        return -1;
    }    
    if(listen(fd,5) < 0){

        perror("fail to listen");
        return -1;
    }
    
    while(1){

        struct sockaddr_in cliaddr;
        bzero(&cliaddr,0);
        socklen_t len = sizeof(cliaddr);
        int connfd = accept(fd,(struct sockaddr *)&cliaddr,&len);

        if(connfd < 0){

            perror("fail to accept");
            return -1;
        }
        printf("----client connected----\n");

        char rbuf[1024] = {0};
        char sbuf[1024] = {0};
        int n = read(connfd,rbuf,sizeof(rbuf));
        if(n > 0){

            printf("recv:%s\n",rbuf);
            sprintf(sbuf,"server+ %s",rbuf);
            write(connfd,sbuf,strlen(sbuf));
        }
        close(connfd);
    }
    return 0;
    }

2.客户端和服务器端点对点聊天

c 复制代码
#include<stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<netinet/ip.h>
#include<unistd.h>
#include<stdint.h>
#include<string.h>
#include<strings.h>

int main(void)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket fail");
        return -1;
    }

    struct sockaddr_in seraddr;
    bzero(&seraddr, sizeof(seraddr));
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(50000);
    seraddr.sin_addr.s_addr = inet_addr("192.168.0.182");

    if (bind(fd, (const struct sockaddr *)&seraddr, sizeof(seraddr)) < 0) {
        perror("bind fail");
        return -1;
    }
    if (listen(fd, 5) < 0) {
        perror("listen fail");
        return -1;
    }

    struct sockaddr_in cliaddr;
    socklen_t len = sizeof(cliaddr);
    int connfd = accept(fd, (struct sockaddr *)&cliaddr, &len);
    if (connfd < 0) {
        perror("accept fail");
        return -1;
    }
    printf("---client connect---\n");

    pid_t pid = fork();
    if (pid < 0) {
        perror("fork fail");
        return -1;
    } else if (pid == 0) {
        // 子进程:发送消息
        char sbuf[1024];
        while (fgets(sbuf, sizeof(sbuf), stdin) != NULL) {
            write(connfd, sbuf, strlen(sbuf));
        }
    } else if(pid > 0) {
        // 父进程:接收消息
        char rbuf[1024];
        int n;
        memset(rbuf, 0, sizeof(rbuf));
        while ((n = read(connfd, rbuf, sizeof(rbuf) - 1)) > 0) {
            rbuf[n] = '\0';
            printf("client: %s\n", rbuf);

        }
    }
    close(connfd);
    close(fd);
    return 0;
}