网络编程:TCP 客户端服务端简单例子

网络编程:TCP 客户端/服务端简单例子

写在前面的话

该例子比较简单,注释得也比较仔细。适合小白学习网络编程。了解TCP下C/S模型编程的基本流程,后续学习,复杂功能其实在process_xx函数实现即可。参考教材:Linux网络编程(第二版)

前置知识:1.多进程:fork()函数 2.linux:标准输入0,标准输出1,标准错误2 3.socket:几个常用API

题目(功能描述)

客户端:1.客户端连接连接服务端后,从标准输入字符串发送给客户端。2.接收到客户端消息后打印出接收到的消息

服务端:服务端接收客户端发送的消息,并计算出接收到的字符总数,发回给客户端

服务端代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 54321
#define BACKLOG 2
//服务端对客户端的处理
void process_coon_server(int s)
{
    ssize_t size = 0;
    char buffer[1024]; //数据缓冲区
    while (1)
    {
        //从套接字读取数据放到缓冲区
        size = read(s, buffer, 1024);
        //没有数据可读
        if (size == 0)
        {
            return;
        }
        //构建收到的字符串
        sprintf(buffer, "%d bytes altogether\n", size);
        //发送给客户端
        write(s, buffer, strlen(buffer) + 1);
    }
}
int main(int argc, char *argv[])
{
    int pid;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    //建立流式套接字
    int ss = socket(AF_INET, SOCK_STREAM, 0);
    if (ss < 0)
    {
        printf("make socket error.\n");
        return -1;
    }
    //设置服务器地址
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(PORT);

    //绑定
    int errb = bind(ss, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (errb < 0)
    {
        printf("bind error.\n");
        return -1;
    }

    //监听
    int errl = listen(ss, BACKLOG);
    if (errl < 0)
    {
        printf("listen error .\n");
        return -1;
    }

    while (1)
    {
        socklen_t addrlen = sizeof(struct sockaddr);

        //接收客户端连接
        int sc = accept(ss, (struct sockaddr *)&client_addr, &addrlen);
        //出错,结束本次循环
        if (sc < 0)
        {
            continue;
        }

        //建立新进程处理客户端连接
        pid = fork();
        if (pid == 0)
        {
            //为了防止误操作,在子进程将监听的socket关闭
            close(ss);
            //处理客户端请求
            process_coon_server(sc);
        }
        else
        {
            //为了防止误操作,在父进程将连接的socket关闭
            close(sc);
        }
    }
}

客户端代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 54321
//服务端对客户端的处理
void process_coon_client(int s)
{
    ssize_t size = 0;
    char buffer[1024]; //数据缓冲区
    while (1)
    {
        size = read(0, buffer, 1024);
        if (size > 0)
        {
            write(s, buffer, size);       //发送给服务器
            size = read(s, buffer, 1024); //从服务器读取数据
            write(1, buffer, size);       //写到标准输出
        }
    }
}
int main(int argc, char *argv[])
{
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    //建立流式套接字
    int ss = socket(AF_INET, SOCK_STREAM, 0);
    assert(ss >= 0);
    //设置服务器地址
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(PORT);

    //将用户输入的字符串IP转换
    inet_pton(AF_INET, argv[1], &server_addr.sin_addr);

    //连接服务器
    connect(ss, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
    process_coon_client(ss);

    //关闭连接
    close(ss);
    return 0;
}

效果演示

[外链图片转存中...(img-ppFREOhe-1651132116680)]

可以看到,程序实现了预期的基本功能。

查看连接情况

在这里插入图片描述

可以看到连接建立是成功的,52410是操作系统为客户端分配的随机端口,54321是服务端监听端口。

你可能感兴趣的:(linux,socket,网络编程)