• TCP通讯程序设计


    1、编程模型函数化

    函数学习

    1)创建套接字

    函数名:socket

    函数原型:Int socket(int domain,int type,int protocol);

    函数功能:创建套接字

    所属头文件:<sys/types.h>、<sys/socket.h>

    返回值:成功:返回对应于新套接字的文件描述符或者套接字的id,失败:返回错误编码

    参数说明:domain:有一系列可取值;type:创建的套接字协议的类型;protocal:协议

    解释:

    int domain,表示套接字要使用的协议簇,协议簇在文件linux/socket.h有详细定义,常用的协议簇:

    AF_UNIX(本机通信);

    AF_INET(TCP/IP -IPv4);

    AF_INET6(TCP/IP - IPv6);

    其中type参数指的是套接字类型;常用的类型有:

    SOCK_STREAM(TCP流);

    SOCK_DGRAM(UDP数据报);

    SOCK_RAW(原始套接字);

    最后一个protocol一般设置为0,也就是当确定套接字使用的协议簇和类型时,这个参数的值就为0,但是有时候创建原始套接字时,并不知道要使用的协议簇和类型,也就是domain参数未知情况下,这时protocol这个参数就起作用了,它可以确定协议的种类。
    socket是一个函数,那么它也有返回值,当套接字创建成功时,返回套接字,失败返回“-1”,错误代码则写入“errno”中。

    2)绑定套接字

    解释:Socket套接字地址:是一个数据结构,基于TCP传输协议为例,其数据结构里面包含了:

    #include<netinet/in.h>
    
    struct sockaddr_in
    {
     unsigned short  sin_family;//地址类型,对于基于TCP/IP传输协议的通信,该值只能是AF_INET;
     unsigned shot int sin_port;//表示端口号,范围在0~65535之间;
     struct in_addr   sin_addr;//32位的IP地址;
     unsigned char  sin_zero[8];//表示填充字节,一般该值为0;
    };

    例子:

    struct sockaddr_in Lewis;
      Lewis.sin_family      = AF_INET;
      Lewis.sin_port        = htons(80);
      Lewis.sin_addr.s_addr = inet_addr("202.96.134.133");
      memset(Lewis.sin_zero,0,sizeof(Lewis.sin_zero));

    对于

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(6666);

    对于选项INADDR_ANY,就是指的是0.0.0.0的地址,表示所有地址,任意地址,用于一台电脑上有多个网卡的情况,方便管理,管理一个套接字就行,不管数据从哪个网卡过来,只要是绑定的端口号过来的数据,都可以接收;而客户端不能使用INADDR_ANY选项;htons   #include <arpa/inet.h> 
        uint16_t htons(uint16_t hostshort); 
        功能: 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)

    htons 是把你机器上的整数转换成“网络字节序”, 网络字节序是 big-endian,也就是整数的高位字节存放在内存的低地址处。而我们常用的 x86 CPU (intel, AMD) 电脑是 little-endian,也就是整数的低位字节放在内存的低字节处。

    举个例子:假定你的port是  0x1234,  在网络字节序里 这个port放到内存中就应该显示成  addr addr+1  0x12 0x34  而在x86电脑上,0x1234放到内存中实际是:  addr addr+1  0x34 0x12 htons 的用处就是把实际内存中的整数存放方式调整成“网络字节序”的方式。

    htonl()  #include <arpa/inet.h>

    功能:将主机的无符号长整形数转换成网络字节顺序。 
      uint32_t htonl(uint32_t hostlong);

    inet_addr() 将一个字符串格式的ip地址转换成一个uint32_t数字格式,但是需要注意的是, 这个函数的返回值在大小端机器上是不同的;

    例如输入一个"192.168.0.1"的字符串, 在内存中的排列(字节从低到高) 0xC0, 0xA8 ,0x00 ,0x4A。 那么在小端序机器上,返回的数字就是0x4a00a8c0 , 而在大端序机器上则是0xc0a8004a

    函数名:bind

    函数原型:Int Bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

    函数功能:绑定套接字:将ip地址与套接字相绑定

    所属头文件:<sys/types.h>、<sys/socket.h>

    返回值:成功:返回对应于新套接字的文件描述符或者套接字的id;失败:返回错误编码

    参数说明:sockfd:要绑定套接字的fd;addr:将套接字与那个地址进行绑定;addrlen:地址长度

    网络字节序:

    3)监听

    listen

    int listen(int sockfd,int backlog)

    作用:1、用来指明服务器已经做好了准备,可以用来接收客户机的请求了。2、用来设置服务器可以接受多少个客户机的连接请求

    参数:sockfd与之关联的套接字的fdBacklog:客户机的数目,即允许多少个客户机来进行连接。

    成功:返回0失败:返回-1

    4)等待连接

    Accept

    int accept(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict len);

    作用:等待客户机来进行连接,如果无客户机来连接,则导致服务器在这里阻塞。

    参数:sockfd:创建的套接字的fdAddr:如果有客户机来进行连接,那么通过本地址来返回客户机的地址。Len:接收到客户机的地址的长度

    成功:返回新的套接字的描述符。后面在发送和接收数据时用这个新的fd来进行操作。

    5)发送数据

    函数名:Send

    ssize_t send(int sockfd,const void *buf,size_t nbytes,int flags);

    作用:发送数据

    参数:sockfd:新的套接字的fd,buf:要发送数据的地址,nbytes:要发送数据的长度,flags:标志

     6)接收数据

    Recv

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

    参数:sockfd:新的套接字的fd,buf:要存数据的地址,nbytes:希望接收多大量的数据,flags:标志

    7)关闭连接

    Close

    8)连接服务器

    Connect

    int connect (int sockfd,const struct sockaddr *addr,socklen_t len)

    参数:新创建的套接字的fdaddr:保存的服务器的地址,len:服务器地址的长度

    成功:返回0

    失败:返回-1

    9)

    #include <arpe/inet.h>
    int inet_pton(int family, const char *strptr, void *addrptr);     //将点分十进制的ip地址转化为用于网络传输的数值格式
            返回值:若成功则为1,若输入不是有效的表达式则为0,若出错则为-1
     
    const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);     //将数值格式转化为点分十进制的ip地址格式
            返回值:若成功则为指向结构的指针,若出错则为NULL

     tcp_server.c

    修改:

    tcp_client.c

  • 相关阅读:
    DS博客作业--线性表
    c博客06-2019-结构体&文件
    C语言博客作业03--函数
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业03--树
    DS博客作业02--栈和队列
    DS博客作业2--线性表
    c博客06-结构体&文件
    C语言博客作业—2019-指针
  • 原文地址:https://www.cnblogs.com/gary-guo/p/5583552.html
Copyright © 2020-2023  润新知