zoukankan      html  css  js  c++  java
  • Linux下TCP/socket编程

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

    本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/9073801.html

    (本篇博客参考了:https://www.cnblogs.com/xiaojiang1025/archive/2016/10/11/5950458.html,源码为我自己所写)

    基本模型:

     

    核心代码:

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    //服务器:  
    
    socket()              //创建socket                    
    struct sockaddr_in    //准备通信地址      
    bind()                //绑定socket和addr
    listen()              //创建listening socket
    accept()              //创建connect socket
    send()/recv()         //进行通信            
    close()               //关闭socket            
    
    //客户端:
    
    socket()              //创建socket
    准备通信地址:服务器的地址
    connect()             //链接socket和通信地址
    send()/recv()         //进行通信
    close()               //关闭socket

    关键函数解释:

    bind()

    //把通信地址和socket文件描述符绑定,用在服务器端,成功返回0,失败返回-1设errno

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

    sockfd: socket文件的fd(returned by socket())

    addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上

    addrlen: 通信地址的大小, 使用sizeof();

     

    listen()

    //创建侦听socket,把sockfd标记的socket标记为被动socket,被动socket表示这个socket只能用来接收即将到来的连接请求,不再用于读写操作和通信,接收连接请求的是accept()

    //成功返回0,失败返回-1设errno

    int listen(int sockfd, int backlog);

    backlog:排队等待“被响应”连接请求队列的最大长度 eg: 接待室的最大长度

     

    accept()

    //创建连接socket,返回连接socket的文件描述符,成功返回文件描述符,失败返回-1设errno

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

    addr : 结构体指针, 用于带出客户端的通信地址

    addlen : 结构体指针, 用于带出通信地址的大小

    ATTENTION: listen()把socket()创建的sockfd变为listening socket, 负责侦听哪个client连接上了(即不但要知道连上没, 还要知道谁连上了, 这个SOCK_STREAM的socket有这个能力), accept()提取排队中的最上面的一个client, 给它一个conneted socket, 这样这个client就可以和server沟通了, 就是说这里有两个socket, 一个负责侦听一个负责通信

     

    send()

    //向指定的socket发送指定的数据,成功返回实际发送数据的大小,失败返回-1设errno

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

    sockfd: 用于通信的socket描述符(returned by accept())

    buf : 被发送数据的缓冲区首地址

    len : 被发送数据的大小

    flags: 发送的标志, 如果给0等同于write()

     

    recv()

    //从指定的socket接收数据,成功返回接收的数据的大小,失败返回-1设errno

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

    sockfd: 用于通信的socket描述符(returned by accept())

    buf: 接收数据的缓冲区首地址

    len: 接收数据的大小

    flags: 发送的标志, 如果给0等同于read()

     

    connect()

    //初始化一个socket的连接,用在客户端,成功返回0,失败返回-1设errno

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

    sockfd: socket文件的fd(returned by socket())

    addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上

    addrlen: 通信地址的大小, 使用sizeof();

    源代码:

     

    1、client端:

    /*
    ./server (local ip) 7575
              自己ip    端口
    */
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/socket.h>
    #include <resolv.h>
    #include <stdlib.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    
    #define MAXBUF 1024
    
    int main(int argc, char **argv)
    {
        int sockfd, len;
        struct sockaddr_in dest;
        char buffer[MAXBUF + 1];
        if (argc != 3) 
        {
        printf(" error format,it must be:
    		%s IP port
    ",argv[0]);
        exit(EXIT_FAILURE);
        }
    
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
        }
        printf("socket created
    ");
    
    
        bzero(&dest, sizeof(dest));
        dest.sin_family = AF_INET;
        dest.sin_port = htons(atoi(argv[2]));
        if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) 
        {
        perror(argv[1]);
        exit(errno);
        }
        if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest))==-1) 
        {
        perror("Connect ");
        exit(errno);
        }
        printf("server connected
    ");
    
        while (1) {
        bzero(buffer, MAXBUF + 1);
        len = recv(sockfd, buffer, MAXBUF, 0);
        if (len > 0)
            printf("recv successful:'%s',%d byte recv
    ",buffer, len);
        else {
            if (len < 0)
            printf("send failure,errno code is %d,err message is '%s'
    ",errno, strerror(errno));
            else
            printf("the other one close ,quit
    ");
            break;
        }
        bzero(buffer, MAXBUF + 1);
        printf("pls send message to send:");
        fgets(buffer, MAXBUF, stdin);
        if (!strncasecmp(buffer, "quit", 4)) 
        {
            printf(" i will quit!
    ");
            break;
        }
        len = send(sockfd, buffer, strlen(buffer) - 1, 0);
        if (len < 0) 
        {
            printf("message '%s' send failure,errno code is %d,errno message is '%s'
    ",buffer, errno, strerror(errno));
            break;
        } else
            printf("message:%s	send successful,%dbyte send!
    ",buffer, len);
        }
        close(sockfd);
        return 0;
    }

    2、server端:

    /*
    ./server (local ip) 7575 5
              自己ip   端口  等待队列大小
    ifconfig -a
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    
    #define MAXBUF 1024
    
    int main(int argc, char *argv[])
    {
        int pid;
        
        int sockfd, new_fd;
        socklen_t len;
        struct sockaddr_in my_addr, their_addr;
        unsigned int myport, lisnum;
        char buf[MAXBUF + 1];
    
        if (argv[2])
            myport = atoi(argv[2]);
        else
            myport = 7575;
    
        if (argv[3])
            lisnum = atoi(argv[3]);
        else
            lisnum = 5;
    
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(myport);
        if (argv[1])
        my_addr.sin_addr.s_addr = inet_addr(argv[1]);
        else
        my_addr.sin_addr.s_addr = INADDR_ANY;
    
        if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1) 
        {
            perror("bind");
            exit(EXIT_FAILURE);
        }
    
        if (listen(sockfd,lisnum ) == -1) 
        {
            perror("listen");
            exit(EXIT_FAILURE);
        }
        printf("wait for connect
    ");    
        len = sizeof(struct sockaddr);
        if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) 
        {
            perror("accept");
            exit(EXIT_FAILURE);
        } 
        else
            printf("server: got connection from %s, port %d, socket %d
    ",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);
             
        while (1) 
        {
              printf("newfd=%d
    ",new_fd);
            bzero(buf, MAXBUF + 1);
            printf("input the message to send:");
          fgets(buf, MAXBUF, stdin);
          if (!strncasecmp(buf, "quit", 4)) 
          {
            printf("i will close the connect!
    ");
            break;
          }
          len = send(new_fd, buf, strlen(buf) - 1, 0);
          if (len > 0)
            printf("message:%s	 send sucessful,send %dbyte!
    ",buf, len);
          else 
          {
            printf("message'%s' send failure!errno code is %d,errno message is '%s'
    ",buf, errno, strerror(errno));
            break;
          }
          bzero(buf, MAXBUF + 1);
    
          len = recv(new_fd, buf, MAXBUF, 0);
          if (len > 0)
            printf("message recv successful :'%s',%dByte recv
    ",buf, len);
          else 
          {
            if (len < 0)
                printf("recv failure!errno code is %d,errno message is '%s'
    ",errno, strerror(errno));
            else
                printf("the other one close quit
    ");
            break;
          }
        }
        close(new_fd);
          close(sockfd);
            return 0;
    }

    运行示例:

     

    PS(被蔡总玩坏了的tcp,23333):

    tz@COI HZAU

    2018/5/22

  • 相关阅读:
    python cookbook 笔记二
    python cookbook 笔记一
    aircrack-ng笔记
    TeamCity 和 Nexus 的使用
    Linux 搭建 nexus 私服【转】
    maven阿里云镜像
    kali linux 破解wpa密码
    python正则表达式二[转]
    Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
    集合解析
  • 原文地址:https://www.cnblogs.com/acm-icpcer/p/9073801.html
Copyright © 2011-2022 走看看