粤嵌GEC6818网络通信学习

本文详细介绍了网络编程的基础,包括IP地址由网络号和主机号组成,TCP和UDP两种通信方式,以及创建套接字、绑定地址、监听连接、接收连接、发送消息等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、网络编程的基础:

IP地址:网络号 + 主机号

网络程序= IP + 端口

二、 两种通信

1. TCP

2.UDP

三、代码描述

1.创建套接字

2.将一个名字和一个套接字绑定到一起

3.网络字节次序

4.IP地址函数转换

5.在一个套接字上倾听连接

6.在一个套接字上接收一个连接

7.连接服务器

8. 从套接字接收信息

9.从套接字发送消息

10.关闭套接字

一、网络编程的基础:

        如果两个计算机想要通信,必须在同一个局域网。

        在一个局域网之内,如果想要进行通信,那么这两者都必须要有唯一一个ID --- IP地址 

IP地址:网络号 + 主机号

        网络号:用来标识局域网

        主机号:用来标识局域网里面的主机

子网掩码的功能是告知主机或路由设备,地址的哪一部分是网络号,包括子网的网络号部分,哪一部分是主机号部分。

  • 在子网掩码中,网络部分和子网络部分对应的位全为“1”主机部分对应的位全为“0”

        11111111 11111111 11111111 11111111 -> 全是网络号,没有主机,因此没有什么作用
        00000000 00000000 00000000 00000000 -> 全部是主机,没有网络,可以的,这是世界最大的网

  • 子网掩码一定是有连续的1和连续的0组成

  • 子网掩码里面的1必须全部相同,0所对应的必须不同

192.168.31.249 -> 点分式ip地址,.隔开的是一个字节
255.255.255.0
        网络号:192.168.31
        主机号:249

255.255.255.0 对应的局域网能容纳的主机最多是:256个 
.0 .1 .255 -> 这三个地址不能用  因此实际上行我们能用253个

  

网络程序= IP + 端口

        端口号用于区分网络程序,现在是2个字节

        0 ~ 1023 -> 知名端口

        1024 ~ 49151 -> 注册端口

网络编程对于两端

        1.服务器 --- 服务器

        2.客户端 --- 客户端的应用程序

二、 两种通信

1. TCP

TCP --- 面向连接的,可靠通信,保证数据的无丢失无失序,有重发机制,也就是数据没有

             成功到达,会重发

服务端:

        1.创建套接字 --- 网络通信是一个文件,这个文件我们就叫套接字,是一个特殊的文件

                                  描述符scokfd

        2.我们需要将服务器的IP地址绑定到套接字

        3.监听连接 --- 创建一个监听队列,建立5个10个可以了

        4.循环等待客户端的连接,如果没有连接则等待,如果有连接则返回一个连接套接字

        5.和客户端进行正常收发

        6.关闭套接字

客户端

        1.创建套接字
        2.准备服务器的ip地址,准备连接
        3.连接服务器
        4.和服务器进行正常收发
        5.关闭套接字

2.UDP

UDP --- 面对无连接的,通信是不可靠的,但是效率要高于TCP,

             大量的实时不可靠通信我们就使用UDP

服务端
        1.创建套接字
        2.绑定地址
        3.等待客户端给你发送信息
        如果等待了客户端的信息,服务器会知道客户端的地址
        根据刚刚得到的客户端的地址给客户端发送信息即可
        4.关闭套接字

客户端
        1.创建套接字
        2.准备服务器地址,准备给服务器发送信息
        3.给服务器发送信息,然后可根据我们自己的项目逻辑来进行收发
        4.关闭套接字

三、代码描述

1.创建套接字

NAME

        

        socket - create an endpoint for communication  --- 创建一个套接字

SYNOPSIS

        #include <sys/types.h>
        #include <sys/socket.h>

        int socket(int domain, int type, int protocol);

                domain传输层的协议
                        AF_UNIX     UNIX协议域,后面我们可以用这个玩意儿来实现进程间通信
                        AF_INET     IPV4
                        AF_INET6    IPV6

                        ......

                type:你采用那种协议进程数据传输
                        SOCK_STREAM 面向连接    -> TCP
                        SOCK_DGRAM  面向无连接  -> UDP
                protocol私有协议
                        我们直接写0  表示一个不知名的协议
                返回值
                        成功返回一个套接字,类似于文件描述符
                        失败返回-1,同时errno被设置  

2.将一个名字和一个套接字绑定到一起


NAME 
        bind --- 将一个名字和一个套接字绑定到一起(赋一个名字给一个套接字)

SYNOPSIS 概述
        #include <sys/types.h>
        #include <sys/socket.h>

        将 my_addr这个地址绑定到sockfd这个套接字上面去

        int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);

                sockfd:套接字  你要绑定到这个套接字上面来   

                my_addr:我们的地址 

                        struct sockaddr这个地址是一个公版
                        根据需求我们自己要选用正确的类型


                        struct sockaddr_in //这个类型是面向网络的  因此我们需要选用这个类型

                        {
                            sa_family_t sin_family; /* 地址族: AF_INET */
                                                这里就是socket第一个参数的填法
                                    
                            u_int16_t sin_port; /* 按网络字节次序的端口 */
                                                端口号  在注册端口里面选用一个即可
                                                8888  === 0x22B8    
                                                -> 0xB822
                            struct in_addr sin_addr; /* internet地址 */
                                                //这个就是我们ip地址  
                                                "192.168.31.249" -> 点分式
                                                 一个字符串给人看的
                                                "192.168.31.249" -> 0xC0A81FF9
                                                -> 网络字节序就是 0xF91FA8C0
                            };

                        /* Internet地址. */
                        struct in_addr {
                                u_int32_t s_addr; /* 按网络字节次序的地址 */
                                             //也就是我们的ip转换成一个整数了                            
                                                };


                addrlen:地址的长度  实际上就是struct sockaddr_in这个类型的长度
                返回值:
                        成功返回0,失败返回-1,同时errno被设置

3.网络字节次序

这个是一个大端模式,如果直接把ip地址给它,不行,会变成反的

因此我们需要将小端模式转换成大端模式

这个是端口转换

SYNOPSIS
       #include <arpa/inet.h>
               
        uint32_t htonl(uint32_t hostlong);

        uint16_t htons(uint16_t hostshort);  //h版本端口小端模式转网络字节序

        uint32_t ntohl(uint32_t netlong);

        uint16_t ntohs(uint16_t netshort);//n版本网络字节序转端口小端

                l:长    4个字节
                s:短    2个字节


        uint16_t htons(uint16_t hostshort);现在我们需要选用这个

4.IP地址函数转换

NAME
       inet_aton,    inet_addr,    inet_network,   inet_ntoa,   inet_makeaddr,
       inet_lnaof, inet_netof - Internet address manipulation routines

SYNOPSIS
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

       int  inet_aton(const char *cp, struct in_addr *inp);
                cp -> inp        

                将在cp中存储的点分十进制字符串类型的IP地址,转换为二进制的IP地址,转换后的值保存在指针inp指向的结构struct in_addr中。


       in_addr_t  inet_addr(const char *cp);//如果是结构体里面用结构体  采用这个就可以了
                cp -> 通过返回值返回in_addr_t        

                它将参数cp所指向的字符串形式的IP地址(“192.168.1.11”)转换为二进制的网络字节序的IP地址形式         

                
       in_addr_t inet_network(const char *cp);//主机
字节序的二进制IP
         

       char *inet_ntoa(struct in_addr in);//将得到的ip地址转换成点分式字符串

       struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);

                将主机字节序的网络地址net和主机地址host合并成一个网络字节序的IP地址。

       in_addr_t inet_lnaof(struct in_addr in);

                从参数in中提取出主机地址,执行成功后返回主机字节顺序形式的主机地址。

5.在一个套接字上倾听连接

NAME 名称
        listen - listen for connections on a socket 在一个套接字上倾听连接
                创建一个监听队列,监听我们的连接
SYNOPSIS 概述
        #include <sys/socket.h>

        int listen(int s, int backlog);
                s:在哪个套接字上面进行监听
                backlog:你需要创建多长的队列
        成功返回0,失败返回-1,同时errno被设置

6.在一个套接字上接收一个连接

NAME 名称
        accept - 在一个套接字上接收一个连接

SYNOPSIS 概述
        #include <sys/types.h>
        #include <sys/socket.h>

        int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
                s:套接字
                addr:保存连接对方的ip地址,实际上就是客户端的
                addrlen:地址的长度,一定要带长度进去
        返回值:
                返回一个连接套接字,服务器的通信是基于这个连接套接字的
                失败返回-1,同时errno被设置

7.连接服务器

NAME
        connect - initiate a connection on a socket
                连接服务器
SYNOPSIS
        #include <sys/types.h>          /* See NOTES */
        #include <sys/socket.h>

        int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
                sockfd:套接字
                addr:服务器的ip地址,你需要提前准备
                addrlen:这个地址的长度
        返回值:
                成功返回0,失败返回-1,同时errno被设置

8. 从套接字接收信息

NAME
        recv, recvfrom, recvmsg - receive a message from a socket
                从套接字接收信息
                TCP下面三个函数都可以用
                但是UDP是无连接的,因此只能使用recvfrom
SYNOPSIS
        #include <sys/types.h>
        #include <sys/socket.h>
       
        ssize_t read(int fd, void *buf, size_t count);

        ssize_t recv(int sockfd, void *buf, size_t len, int flags);

        ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                struct sockaddr *src_addr, socklen_t *addrlen);
        前面三个参数请参数read的
                flags:一个标志  填0即可
                src_addr:保存对方的ip地址
                addrlen:保存对方的ip地址长度
        返回值:
                成功返回实际读到的字节数
                失败返回-1,同时errno被设置   

9.从套接字发送消息

NAME
        send, sendto, sendmsg - 从套接字发送消息
        发送信息
                TCP下面三个函数都可以用
                UDP只能使用sendto
SYNOPSIS
        #include <sys/types.h>
        #include <sys/socket.h>

        ssize_t write(int fd, const void *buf, size_t count);

        int send(int s, const void *msg, size_t len, int flags);

        int  sendto(int s, const void *msg, size_t len, int flags, const struct
        sockaddr *to, socklen_t tolen);
                flags:一个标志
                to:对方的ip地址 你要把这个消息发送给谁
                tolen:你的地址的长度
        返回值:
                成功返回实际发送的字节数
                失败返回-1,同时errno被设置

10.关闭套接字

NAME
        shutdown - shut down part of a full-duplex connection
                关闭套接字
SYNOPSIS
        #include <sys/socket.h>
        int close(int fd);//关闭套接字的读写
        int shutdown(int sockfd, int how);
        sockfd:套接字
        how:怎么关闭
                SHUT_RD     关闭读
                SHUT_WR     关闭写 
                SHUT_RDWR   关闭读写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值