Linux Socket 编程初入门(3)

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    char buf[MAXLINE];
    int sockfd, n;
    char *str;
   
    if (argc != 2)
    {
        fputs("usage: ./client message\n", stderr);
        exit(1);
    }
    str = argv[1];
   
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);
   
    // 由于客户端不需要固定的端口号,因此不必调用 bind(),客户端的端口号由内核自动分配。
    // 注意,客户端不是不允许调用 bind(),只是没有必要调用 bind() 固定一个端口号,
    // 服务器也不是必须调用 bind(),但如果服务器不调用 bind(),内核会自动给服务器分配监听端口,
    // 每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

write(sockfd, str, strlen(str));

n = read(sockfd, buf, MAXLINE);
    printf("Response from server:\n");
    write(STDOUT_FILENO, buf, n);
    printf("\n");
    close(sockfd);
    return 0;
}

把上面的代码保存到文件 client.c 文件中,并执行下面的命令编译:

$ gcc client.c -o client

然后运行编译出来的 client 程序:

$ ./client hello

此时服务器端会收到请求并返回转换为大写的字符串,并输出相应的信息:

而客户端在发送请求后会收到转换过的字符串:

在客户端的代码中有两点需要注意:
   1. 由于客户端不需要固定的端口号,因此不必调用 bind(),客户端的端口号由内核自动分配。
   2. 客户端需要调用 connect() 连接服务器,connect 和 bind 的参数形式一致,区别在于 bind 的参数是自己的地址,而 connect 的参数是对方的地址。
至此我们已经使用 socket 技术完成了一个最简单的客户端服务器程序,虽然离实际应用还非常遥远,但就学习而言已经足够了。

提升服务器端的响应能力

虽然我们的服务器程序可以响应客户端的请求,但是这样的效率太低了。一般情况下服务器程序需要能够同时处理多个客户端的请求。可以通过 fork 系统调用创建子进程来处理每个请求,下面是大体的实现思路:

listenfd = socket(...);
bind(listenfd, ...);
listen(listenfd, ...);
while (1)
{
    connfd = accept(listenfd, ...);
    n = fork();
    if (n == -1)
    {
        perror("call to fork");
        exit(1);
    }
    else if (n == 0)
    {
        // 在子进程中处理客户端的请求。
        close(listenfd);
        while (1)
        {
            read(connfd, ...);
            ...
            write(connfd, ...);
        }
        close(connfd);
        exit(0);
    }
    else
    {
        close(connfd);
    }   
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/80debd677267f4f8dc2be2a17fee05cd.html