乐趣区

关于c:Linux网络开发必学教程2服务端编程初体验

客户端 / 服务端 编程模式

  • 服务端长期保留于网络(公开本人的 IP 地址),并期待客户端连贯
  • 客户端发动连贯动作,并期待服务端回应
  • 特点:

    • 服务端无奈被动连贯客户端
    • 客户端只能依照预约义的形式(协定)连贯服务端

服务端编程模式

1. 筹备网络连接
2. 绑定端口
3. 进入端口监听状态
4. 期待连贯 

服务端外围工作:绑定 & 监听 & 接管

  • 绑定:int bind(int sock, struct sockaddr *addr, socklen_t addrlen);
  • 监听:int listen(int sock, int backlog);
  • 接管:int accept(int sock, struct sockaddr *addr, socklen_t addrlen);

深度分析服务端

  • 服务端 socket 只用于接管连贯,不进行理论通信
  • 当接管到连贯时,accept() 函数返回与客户端通信的 socket
  • 服务端 socket 产生用于通信的客户端 socket

所以,socket 到底是什么玩意?如何了解?

深刻了解 socket() 函数

  • socket() 是什么?

    • socket() 是一个多功能函数
  • socket() 返回的又是什么?

    • socket() 的返回值是用于通信的资源标识符
  • socket() 还能做什么?

    • socket() 可提供不同类型的通信性能(本地过程间通信)

编程试验:服务端编程初体验

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int clinet = 0;
    struct sockaddr_in caddr = {0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = {0};
    int r = 0;

    server = socket(PF_INET, SOCK_STREAM, 0);

    if (server == -1) {printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8899);

    if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {printf("server bind error\n");
        return -1;
    }

    if (listen(server, 1) == -1) {printf("server listen error\n");
        return -1;
    }

    printf("server start success\n");

    asize = sizeof(caddr);

    clinet = accept(server, (struct sockaddr*)&caddr, &asize);

    if (clinet == -1) {printf("client accept error\n");
        return -1;
    }

    printf("client: %d\n", clinet);

    len = 0;

    do {
        int i = 0;
        
        r = recv(clinet, buf, sizeof(buf), 0);

        if (r > 0) {len += r;}

        for (i=0; i<r; ++i) {printf("%c", buf[i]);
        }
    } while (len < 64);

    printf("\n");

    send(clinet, "hello word!", 12, 0);

    sleep(1);

    close(clinet);
    close(server);

    return 0;
}

INADDR_ANY => "0.0.0.0", 示意本机的连贯全副承受(如,本机有多个网卡进而有多个 IP 时)

客户端 / 服务端 编程的外围模式

  • 服务端长时间运行(死循环)接管客户端的申请
  • 客户端连贯后向服务端发送申请(协定数据)

服务端外围编程模式

编程试验:客户端 / 服务端编程试验

  1. 服务端继续监听客户端连贯
  2. 服务端被连贯后 echo 客户端数据
  3. 服务端接管到 quit 后断开连接
  4. 客户端接管用户输出并发送到服务端

服务端

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int client = 0;
    struct sockaddr_in caddr = {0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = {0};
    int r = 0;

    server = socket(PF_INET, SOCK_STREAM, 0);

    if (server == -1) {printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8888);

    if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {printf("server bind error\n");
        return -1;
    }

    if (listen(server, 1) == -1) {printf("server listen error\n");
        return -1;
    }

    printf("server start success\n");

    while (1) {asize = sizeof(caddr);

        client = accept(server, (struct sockaddr*)&caddr, &asize);

        if (client == -1) {printf("client accept error\n");
            return -1;
        }

        printf("client: %d\n", client);

        do {r = recv(client, buf, sizeof(buf), 0);
            if (r > 0) {printf("Receive: %s\n", buf);

                if (strcmp(buf, "quit") != 0) {len = send(client, buf, r, 0);
                }
                else {break;}
            } 
        } while (r > 0);

        close(client);
    }

    close(server);

    return 0;
}

客户端

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int sock = 0;
    struct sockaddr_in addr = {0};
    int len = 0;
    char buf[128] = {0};
    char input[32] = {0};
    int r = 0;

    sock = socket(PF_INET, SOCK_STREAM, 0);

    if (sock == -1) {printf("socket error\n");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("192.168.2.46");
    addr.sin_port = htons(8888);

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {printf("connect error\n");
        return -1;
    }

    printf("connect success\n");

    while (1) {printf("Input:");

        scanf("%s", input);

        len = send(sock, input, strlen(input) + 1, 0);

        r = recv(sock, buf, sizeof(buf), 0);

        if (r > 0) {printf("Receive: %s\n", buf);
        }
        else {break;}
    }

    close(sock);

    return 0;
}

思考:如何加强服务端能力,同时反对多个客户端?

退出移动版