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的数据。

  • 相关阅读:
    c#冒泡排序
    C# 虚方法(virtual)覆盖(override) 隐藏(new) 重载
    Javascript 大括号
    C# const.static.readonly.
    热点链接(img map area)
    WeiBo返回错误码的二种方式
    Cookie跨域操作
    synchronized(this)与synchronized(class)
    线程安全场景备忘
    git新建一个分支setupstream
  • 原文地址:https://www.cnblogs.com/mylinux/p/5198383.html
Copyright © 2011-2022 走看看