分析一个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>\n", 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] = '\0';  // overwrite the '\n' 
        
        if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
        {
           printf("fail to get\n");
            return;
        }
        printf("socket\n");show_time();
        if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0)
        {
            printf("fail to connect server\n");
            return;
       }
       printf("send\n");show_time();
       send(sockfd, command, strlen(command)+1, 0);
       printf("send over\n");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\n", strerror(errno));
      exit(-1);
   }
#ifdef _DEBUG_
   printf("socket is %d\n", 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\n", counter++); show_time();
        }
        recv(connfd, buf, N, 0);
        printf("recvd from client\n"); show_time();
        send(connfd, "54321", 6, 0);
        printf("sent to client\n"); 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\n", counter++); show_time();
        }

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

  server打印 ”recvd from client “  

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

 

上面的实验说明了:

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

posted @ 2016-02-18 15:36  oucaijun  阅读(1425)  评论(0编辑  收藏  举报
下载TeamViewer完整版 下载TeamViewer