CS模型的核心精要

CS模型的核心精要

1、服务端编程初体验

1.1、客户端/服务端编程模式

  • 服务端长期暴露网络,并等待客户端连接
  • 客户端发起连接动作,并等待服务端回应
  • 特点:
    • 服务端无法主动连接客户端
    • 客户端只能按照预定义的方式连接服务端

1.2、服务端编程模式

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

1.3、服务端核心工作:绑定&监听&接收

  • 绑定
    • int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  • 监听
    • int listen(int sockfd, int backlog);
  • 接收
    • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

1.4、深度剖析服务端

  • 服务端socket只用于接收连接,不进行实际通信
  • 当接收到连接时,accpet()函数返回与客户端通信的socket
  • 服务端socket产生用于通信的客户端socket
  • 所以,socket究竟是什么玩意?如何理解?

1.5、深度理解socket()函数

  • socket()是什么?
    • socket()是一个“多功能”函数
  • socket()返回的又是什么?
    • socket()的返回值是用于通信的资源标识符
  • socket()还能做什么?
    • socket()可提供不同类型的通信功能(本地进程间通信)

1.6、服务端编程示例

//2-2.c

#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 err\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 err\n");
        return -1;
    }

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

    asize = sizeof(caddr);

    client = accept(server,(struct sockaddr*)&caddr, &asize);
    if(client == -1)
    {
        printf("client accept err\n");
        return -1;
    }

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


    do
    {
        int i = 0;

        r = recv(client, 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(client, "hello world!", 12, 0);

    sleep(1);

    close(client);
    close(server);
    return 0;
}

1.7、客户端/服务端编程的核心模式

  • 服务端长时间运行(死循环)接收客户端请求
  • 客户端连接后向服务端发送请求(协议数据)
  • 服务端核心编程模式
  • 客户端/服务端编程的核心模式

1.8、编程实验

  1. 服务端持续监听客户端连接
  2. 服务端被连接后echo客户端数据
  3. 服务端接收到quit后断开连接
  4. 客户端接收用户输入并发送到服务端
//client.c
#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;
    int r = 0;
    char buf[128] = {0};
    char input[32] = {0};

    sock = socket(PF_INET,SOCK_STREAM,0);
    if(sock == -1)
    {
        printf("socket err\n");
        return -1;
    }

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

    if(connect(sock,(struct sockaddr*)&addr,sizeof(addr)) == -1)
    {
        printf("connect err\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("Recv : %s\n", buf);
        }
        else
        {
            break;
        }

    }
    close(sock);

    return 0;
}
//server.c
#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 err\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 err\n");
        return -1;
    }

    if( listen(server,1) == -1 )
    {
        printf("listen err\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 err\n");
            return -1;
        }

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

        do
        {
            r = recv(client, buf, sizeof(buf), 0);

            if( r > 0)
            {
                printf("Recv: %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;
}

1.9、思考

如何增强服务端能力,同时支持多个客户端?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值