socket编程

读取socket编程

socket接口

  • socket函数 创建套接字的函数

    • 函数原型

       #include <sys/socket.h>
       int socket(int domain, int type, int protocol);
    • 函数参数

      NO.含义参数可选项
      1协议域domin AF_INET:IPv4;AF_INET6:IPv6;AF_LOCAL:Unix域
      2类型type SOCK_STREAM:流式套接字;SOCK_DGRAM:数据报套接字;SOCK_RAW:原始套接字
      3协议protocol 0:自动根据type匹配协议;IPPROTO_TCP/IPPROTO_UDP
    • 返回值

      • 失败返回-1,成功返回套接字的描述符号

  • close函数 关闭套接字的函数

    • 函数原型

      int close(int sockfd)
      int shutdown(int sockfd,int howto)
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号sockfd
      2关闭方式howto SHUT_RD关闭连接的读, SHUT_WDWR关闭连接的写和读, SHUT_WR关闭连接的写。
  • bind函数 绑定函数assigning a name to a socket

    • 函数原型

       #in #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
       int bind(int sockfd, const struct sockaddr *addr,
                      socklen_t addrlen);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号sockfd
      2地址和端口号address
      3address缓冲区的大小address_len
    • 返回值

      • 成功返回0,失败返回socket_error

  • listen函数 监听函数

    • 函数原型

        #include <sys/types.h>          /* See NOTES */
        #include <sys/socket.h>
             int listen(int sockfd, int backlog);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号sockfd
      2连接的最大上限backlog
    • 返回值

      • 成功返回0,失败返回-1。

  • connect函数 连接函数

    • 函数原型

         #include <sys/types.h>          /* See NOTES */
         #include <sys/socket.h>
          int connect(int sockfd, const struct sockaddr
          *addr,socklen_t addrlen);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号sockfd
      2服务器的socket地址addr
      3服务器的socket地址的长度addrlen
    • 返回值

      • 成功返回0,失败返回-1。

  • accept函数 接受函数

    • 函数原型

      #include <sys/types.h>          /* See NOTES */
      #include <sys/socket.h>
      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号sockfd
      2客户端的socket地址addr
      3客户器的socket地址的长度addrlen
    • 返回值

      • 成功返回连接套接字的文件描述符号,失败返回-1。

  • write函数 发送数据函数

    • 函数原型

       #include <unistd.h>
      ssize_t write(int fd, const void *buf, size_t count);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号fd
      2写入的数据buf
      3写入的数据的长度len
    • 返回值

      • 成功返回连接套接字的文件描述符号,失败返回-1。

  • read函数 读取数据函数

    • 函数原型

          #include <unistd.h>
          ssize_t read(int fd, void *buf, size_t count);
    • 函数参数

      NO.含义参数可选项
      1套接字文件描述符号fd
      2写入的数据buf
      3读取的数据的长度len
    • 返回值

      • 返回值为0代表读到文件的结束,>0代表实际读到的字节数,<0代表出错。


socket流程

客户端

  • 打开套接字

  • 连接服务器

  • 写入读取数据

  • 关闭套结字

服务端

  • 打开监听的套结字

  • 设置监听套结字的地址

  • 绑定

  • 监听

  • 打开连接的套结字

  • 读取数据

  • 关闭套结字


    下面是一个基于tcp的服务器/客户端模型代码,可以实现多个客户端连接服务器并且下载文件。

    sever.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <sys/stat.h>
    #include <sys/sendfile.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <pthread.h>
     
    void show_info(int connfd){
        struct sockaddr_in local_addr;
        bzero(&local_addr,sizeof(local_addr));
        socklen_t local_addr_len = sizeof(local_addr);
        getsockname(connfd,(struct sockaddr*)&local_addr,&local_addr_len);
        printf("server local %s:%d\n",inet_ntoa(local_addr.sin_addr),ntohs(local_addr.sin_port));
         
        struct sockaddr_in peer_addr;
        bzero(&peer_addr,sizeof(peer_addr));
        socklen_t peer_addr_len = sizeof(peer_addr);
        getpeername(connfd,(struct sockaddr*)&peer_addr,&peer_addr_len);
        printf("server peer %s:%d\n",inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port));
    }
    void Handle(int connfd){
        
     
        char buf[BUFSIZ];
        for(;;){
            bzero(buf,BUFSIZ);
            ssize_t len;
            if((len = read(connfd,buf,BUFSIZ-1)) == -1){
                perror("read err");
                pthread_exit(1);
            }
            if(0 == len){
                break;
            }
            printf("server recv:%s\n",buf);
             
            int fd = open(buf,O_RDONLY);
            if(-1 == fd){
                perror("open file err");
               // exit(1);
            }
            struct stat file_stat;
            fstat(fd,&file_stat);
            if(-1 == sendfile(connfd,fd,NULL,file_stat.st_size)){
                perror("sendfile err");
               // exit(1);
            }
            close(fd);
        }   
        close(connfd);
    }
    int main(int argc,char* argv[]){
        if(3 != argc){
            printf("usage:%s <ip> <#port>\n",argv[0]);
            return 1;
        }
     
        int listenfd = socket(AF_INET,SOCK_STREAM,0);
        if(-1 == listenfd){
            perror("listenfd open err");
            return 1;
        }
        printf("socket create OK\n");
         
        int flag = 1;
        setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));    
     
        struct sockaddr_in local_addr;
        bzero(&local_addr,sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_addr.s_addr = inet_addr(argv[1]);
        local_addr.sin_port = htons(atoi(argv[2]));
     
        if(-1 == bind(listenfd,(struct sockaddr*)&local_addr,sizeof(local_addr))){
            perror("bind err");
            return 1;
        }
        printf("bind OK\n");
     
        if(-1 == listen(listenfd,10)){
            perror("listen err");
            return 1;
        }
        printf("listen OK\n");
        while(true){
                struct sockaddr_in remote_addr;
                bzero(&remote_addr,sizeof(remote_addr));
                socklen_t remote_addr_len = sizeof(remote_addr);
                int connfd = accept(listenfd,(struct sockaddr*)&remote_addr,&remote_addr_len);
                if(-1 == connfd){
                    perror("accept err");
                    return 1;
                }
                printf("accept %s:%d\n",inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port));
                show_info(connfd);
                pthread_t tid;
                pthread_create(&tid,NULL,reinterpret_cast<void*(*)(void*)>(Handle),reinterpret_cast<void*>(connfd));
                pthread_detach(tid);
        }
        close(listenfd);
     
    }

    client.cpp

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
     
    void show_info(int connfd){
        struct sockaddr_in local_addr;
        bzero(&local_addr,sizeof(local_addr));
        socklen_t local_addr_len = sizeof(local_addr);
        getsockname(connfd,(struct sockaddr*)&local_addr,&local_addr_len);
        printf("client local %s:%d\n",inet_ntoa(local_addr.sin_addr),ntohs(local_addr.sin_port));
         
        struct sockaddr_in peer_addr;
        bzero(&peer_addr,sizeof(peer_addr));
        socklen_t peer_addr_len = sizeof(peer_addr);
        getpeername(connfd,(struct sockaddr*)&peer_addr,&peer_addr_len);
        printf("clinet peer %s:%d\n",inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port));
    }
    int main(int argc,char* argv[]){
        if(3 != argc){
            printf("usage:%s <ip> <#port> \n",argv[0]);
            return 1;
        }
     
        int connfd = socket(AF_INET,SOCK_STREAM,0);
        if(-1 == connfd){
            perror("socket err");
            return 1;
        }
        struct sockaddr_in remote_addr;
        bzero(&remote_addr,sizeof(remote_addr));
        remote_addr.sin_family = AF_INET;
        remote_addr.sin_addr.s_addr = inet_addr(argv[1]);
        remote_addr.sin_port = htons(atoi(argv[2]));    
        if(-1 == connect(connfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))){
            perror("connect err");
            return 1;
        }
        show_info(connfd);
     
        char buf[BUFSIZ];
        bzero(buf,BUFSIZ);
        while(fgets(buf,BUFSIZ,stdin) != NULL){
            write(connfd,buf,strlen(buf)-1);
            printf("client send:%s\n",buf);
            bzero(buf,BUFSIZ);
            // sendfile(fd,connfd,NULL,);
            if(-1 == read(connfd,buf,BUFSIZ)){
                perror("read err");
                return 1;
            }
            printf("client recv:%s\n",buf);
        }
        close(connfd);
    }

    udp是面向无连接的,函数接口如下图所示:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值