zoukankan      html  css  js  c++  java
  • 分析一个socket通信: server/client

    分析一个socket通信: server/client1

    server 

    1. 创建一个server_socket文件,并绑定端口,然后监听端口 (socket, bind, listen)

    2. 查询该端口是否有客户端的连接:
    while(1)
    {
    查询这个端口是否有来自client的消息;(accept)// accept: input is server_socket_fd ; ret value is client_socket_fd
    如果有,返回client_socket_fd, 并把消息读出来 (rcv from client_socket_fd); 当然这个时候server也可以send to client_socket.
    }

    client
    1. 创建一个client_socket文件,绑定端口和server ip,然后通过这个socket去和server的socket连接起来 (socket, connect);
    2. 连接成功后,client往client_socket写东西(send to client_socket_fd). 当然这个时候client也可以rcv from client_socket.

    client_socket文件的作用是client和server之间的一个通信管道。

     

    debug代码:

    //client:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    #define N 128
    
    typedef struct sockaddr SA;
    
    extern void show_time(void);
    
    int main(int argc, char *argv[])
    {
       int sockfd, fd, nbyte;
       char command[32];
       struct sockaddr_in server_addr;
    
       if (argc < 3)
        {
            printf("Usage : %s <server_ip> : <port>
    ", argv[0]);
            exit(-1);
        }    
      
       memset(&server_addr, 0, sizeof(server_addr));
       server_addr.sin_family = PF_INET;
       server_addr.sin_port = htons(atoi(argv[2]));
       server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    
       while ( 1 )
        {
            printf("<client> ");
            fgets(command, 32, stdin);
            command[strlen(command)-1] = '';  // overwrite the '
    ' 
            
            if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
            {
               printf("fail to get
    ");
                return;
            }
            printf("socket
    ");show_time();
            if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0)
            {
                printf("fail to connect server
    ");
                return;
           }
           printf("send
    ");show_time();
           send(sockfd, command, strlen(command)+1, 0);
           printf("send over
    ");show_time();
           close(sockfd);
        }
    
       return 0;
    }
    //break client.c:41 
    //server:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    #include <dirent.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    #define N 128
    
    typedef struct sockaddr SA;
    extern void show_time(void);
    
    int main(int argc, char *argv[])
    {
       int listenfd, connfd;
        char buf[N];
       struct sockaddr_in server_addr;
    
      // XXX:step 1  int socket(int domain, int type, int protocol);
       if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
       {
          fprintf(stderr, "fail to socket : %s
    ", strerror(errno));
          exit(-1);
       }
    #ifdef _DEBUG_
       printf("socket is %d
    ", listenfd);
    #endif  
    
      // XXX:step 2  int bind(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
       memset(&server_addr, 0, sizeof(server_addr));
       server_addr.sin_family = PF_INET;
       server_addr.sin_port = htons(8888);
       server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        if (bind(listenfd, (SA *)&server_addr, sizeof(server_addr)) < 0)
        {
            perror("fail to bind");
            exit(-1);
        }
    
        listen(listenfd, 5);
        static int counter = 0;
        while ( 1 )
        {
            if ((connfd = accept(listenfd, NULL, NULL)) < 0)
            {
                perror("fail to accept"); show_time();
                break;
            }else{
                printf("a connect from client accepted, counter = %d
    ", counter++); show_time();
            }
            recv(connfd, buf, N, 0);
            printf("recvd from client
    "); show_time();
            send(connfd, "54321", 6, 0);
            printf("sent to client
    "); show_time();
            close(connfd);
        }
    
       return 0;
    }

    调试:

    gcc -g client.c show_time.c -o client
    gcc -g server.c show_time.c -o server

    1. 打断点:

    //break client.c:41

    2. 跑server 

    3. 单步跑client,

      当line47跑完  if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0) 的时候,

      server打印“a connect from client accepted, counter = 0” 

    if ((connfd = accept(listenfd, NULL, NULL)) < 0)
            {
                perror("fail to accept"); show_time();
                break;
            }else{
                printf("a connect from client accepted, counter = %d
    ", counter++); show_time();
            }

      当line53跑完  send(sockfd, command, strlen(command)+1, 0) 的时候,

      server打印 ”recvd from client “  

    recv(connfd, buf, N, 0);
    printf("recvd from client
    "); show_time();

    上面的实验说明了:

    socket通信的几个函数接口之间的关系和时序。accept阻塞地等待client的connect接入;recv阻塞地等待client send的数据。

  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/mylinux/p/5198383.html
Copyright © 2011-2022 走看看