• linux网络编程之tcp


    相关函数

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

    参数:
    domain:
    AF_INET
    AF_INET6
    AF_UNIX,AF_LOCAL
    AF_NETLINK
    AF_PACKET
    type:
    SOCK_STREAM: 流式套接字,唯一对应于TCP
    SOCK_DGRAM:数据报套接字,唯一对应着UDP
    SOCK_RAW:原始套接字
    protocol:
    一般填0,原始套接字编程时需填充
    返回值
    成功返回文件描述符
    出错返回-1
    如果是IPV6编程,要使用struct sockddr_in6结构体(man 7 IPV6),通常使用struct sockaddr_storage来编程。

    int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
    
    • 1

    参数
    sockfd:通过socket()函数拿到的fd
    addr:采用struct sockaddr的结构体地址,通用结构体
    struct sockaddr{
    sa_family_t sa_family;
    char sa_data[4];
    }
    struct sockaddr_in{ 基于Internel通信结构体
    as_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
    sin_zero , //填充字节,需清零
    }
    struct in_addr{
    uint32_t s_addr;
    }
    addrlen:地址长度

    int listen(int sockfd,int backlog);
    
    • 1

    参数:
    sockfd: 通过socket()函数拿到的fd;
    backLog:同时允许几路客户端和服务器进行正在连接的过程(正在三次握手),一般填5。

    返回值:
    成功返回0
    出错返回-1
    listen(fd,5);//表示系统允许11(2*5+1)个客户端同时进行三次握手

    阻塞等待客户端连接请求
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    
    • 1
    • 2

    参数
    sockfd:经过前面socket()创建并通过bind(),listen()设置过的fd
    addr:指向存放地址信息的结构体的首地址
    获取客服端IP地址和端口号
    addrlen:存放地址信息的结构体的大小
    返回值
    成功,返回返回已经建立连接的新的newfd
    出错,返回-1

    int connect (int sockfd, struct sockaddr * serv_addr, int addrlen)
    
    • 1

    参数:
    sockfd

    TCP服务端实现步骤:

    1.socket函数创建一个(监听)套接字
    2.bind函数给套接字绑定地址(IP + Port)。即给套接字提高网络连接路口
    3.listen函数将套接字设置为监听状态,相当于将手机设置为待机状态。调用listen 函数实现。
    4.accept函数阻塞接收客户端连接。
    5.收发数据,调用 send/write 和 recv/read 函数实现。
    6.调用 close 函数实现关闭客服端连接。

    TCP服务端代码

    tcp_ser.c

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    
    #define SERV_PORT 8888
    #define SERV_IP_ADDR "192.168.11.128"
    #define BACKLOG 5
    #define BUFSIZE 1024
    #define QUIT_STR "QUIT"
    int main()
    {
            int sockfd;
        //1.创建套接字
            sockfd=socket(AF_INET,SOCK_STREAM,0);
            if(sockfd<0)
            {
                    perror("socket");
                    exit(1);
            }
        //2.给套接字绑定地址
            struct sockaddr_in myaddr;
            //清零myaddr结构体里的数据
            bzero(&myaddr,sizeof(myaddr));
            //初始化myaddr结构体
            myaddr.sin_family=AF_INET;   //协议簇
            myaddr.sin_port=htons(SERV_PORT); //指定端口,主机字节序转换为网络字节序
            myaddr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);//指定IP地址,将字符串转为无符号整型
            //inet_pton(AF_INET,SERV_IP_ADDR,(void *)myaddr.sin_addr_s_addr);
    
            int ret=bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr));
            if(ret ==-1)
            {
                    perror("bind");
                    exit(2);
            }
       //3.使套接字能够监听,能够被其他客服端连接
            int res_lis=listen(sockfd,BACKLOG);
     if(res_lis==-1)//表示系统允许11(2*5+1)个客户端同时进行三次握手
            {
                    perror("listen");
                    //exit(3);
            }
            char buff[BUFSIZE];
    
    
       //4.阻塞等待接受客服端连接
            struct sockaddr_in saddr;
            bzero(&saddr,sizeof(saddr));
            //等待连接
            socklen_t length = sizeof(saddr);
            int newfd=accept(sockfd,(struct sockaddr *)&saddr,&length);
            if(newfd<0)
            {
                    perror("accept");
                    exit(5);
            }
            while(1)
            {
                            memset((void *)buff,0,1024);
                            int ret2=read(newfd,buff,sizeof(buff));
                            if(ret2<=0)
                            {
                                    break;
                            }
                             /*int ret2=recv(newfd,buff,BUFSIZE-1,0);
                             if(ret2==0)
                            {       
                  break;
                            }*/
    
                             printf("receive data is %s\n",buff);
                    //判断是否接受到的数据是不是QUIT_STR,是的话,就退出此次循环
                            if(!strncasecmp(buff,QUIT_STR,strlen(QUIT_STR)))
                            {
                                    printf("client is exiting\n");
                                    break;
                            }
            }
            close(newfd);
    
    
            close(sockfd);
            return 0;
    }
                                                                                                                                                                                              
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    TCP 客户端实现步骤:

    1.socket函数创建一个套接字。
    2.(可以绑定也可以不绑定)bind函数给套接字绑定地址,如果没有绑定,系统将自动给套
    接字分配地址。
    3.connect函数连接服务器。
    4.收发数据,调用 send/write 和 recv/read 函数实现。
    5.close函数断开连接

    TCP 客户端代码

    tcp_cli.c

    #include 
    #include 
    #include           /* See NOTES */
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define  SERV_PROT 8888
    #define  SERV_IP_ADDR "192.168.11.128"
    #define  BUFSZIE 1024
    #define  QUIT_STR "QUIT"
    int main()
    {
            int sockfd;
            //1.创建一个套接字
            sockfd=socket(AF_INET,SOCK_STREAM,0);
    
            //2.不调bind函数来给套接字绑定地址,由系统自动分配
            //3.连接服务器件
            struct sockaddr_in saddr;
            saddr.sin_family=AF_INET;
            saddr.sin_port=htons(SERV_PROT);
            saddr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);
            if(connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)) == -1)
            {
                    perror("connect");
                    exit(1);
            }
            char buffer[1024];
            while(1)
            {
                    memset(buffer,0,1024);
                    if(fgets(buffer,1024,stdin)==NULL)
                    {
                            continue;
                    }
                    send(sockfd,buffer,sizeof(buffer),0);
    
                    if(!strncasecmp(buffer,QUIT_STR,strlen(QUIT_STR)))
                    {
                            break;
                     }
            }
            close(sockfd);
            return 0;
    }
    
                                                           
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    执行结果

    请添加图片描述
    客户端向服务端发送数据,当发送数据为quit时,就服务端和客服端的连接。

  • 相关阅读:
    【工具】咸鱼之王辅助小助手来了!
    来可LCWLAN-600P产品使用和常见问题说明
    Deterministic Policy Gradient Algorithms
    MySQL性能优化实践:SQL查询优化之使用只读索引、IN方法和临时表分批查询(附加:索引的创建删除命令)
    渗透测试-基于浏览器的口令暴破与图形验证码识别
    D咖饮品机器人惊艳亮相:智能硬件改变生活习惯
    js逆向之浏览器环境补充
    WPF 控件专题 ListView 样式(斑马线)
    List操作的一些常见问题
    ansible 调研
  • 原文地址:https://blog.csdn.net/m0_57678852/article/details/128174004