【Linux系统编程】TCP实现--socket

使用套接字socket实现服务器和客户端之间的TCP通信。

流程如下:

实现代码:

c 复制代码
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <ctype.h>

#define SERV_PORT 9527

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}


int main(int argc, char *argv[])
{
    struct sockaddr_in serv_addr, client_addr;
    socklen_t client_addr_len;
    char buf[BUFSIZ], client_IP[1024];
    //1. 创建监听套接字
    int lfd = socket(AF_INET,  //IPV4
                    SOCK_STREAM, 
                    0);
    if(lfd == -1) //check RETURN VALUE
    {
        sys_err("socket error");
    }
    //2. 绑定本地的IP地址和端口号
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int ret = bind(lfd,  (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(ret == -1)
    {
        sys_err("bind error");
    }

    //3. 设置监听
    int ret_listen = listen(lfd, 128);
    if(ret_listen == -1)
    {
        sys_err("listen error");
    }
    
    //4. 阻塞等待,连接的到达,连接成功后返回通信用的套接字
    client_addr_len = sizeof(client_addr);
    int cfd = accept(lfd, (struct sockaddr*)&client_addr, &client_addr_len);
    if(cfd == -1)
    {
        sys_err("accept error");
    }
    printf("client ip is %s, port is %d\n",
             inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)),
             ntohs(client_addr.sin_port));

    //5. 开始通信
    while(1)
    {
        ssize_t ret_acc = read(cfd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, ret_acc);

        for(int i = 0; i < ret_acc; i++)
        {
            buf[i] = toupper(buf[i]);
        }
        write(cfd, buf, ret_acc);
    }

    close(lfd);
    close(cfd);

    return 0;
}
c 复制代码
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <ctype.h>

#define SERV_PORT 9527

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}


int main(int argc, char *argv[])
{
    int cfd;
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
    char buf[BUFSIZ];
    int cnt = 10;

    //1. 创建监听套接字
    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1) 
    {
        sys_err("socket error");
    }

    int ret = connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(ret != 0)
    {
        sys_err("connect error");
    }

    while(cnt--)
    {
        write(cfd, "hello\n", 6);
        ret = read(cfd, buf, sizeof(buf));
        write(STDERR_FILENO, buf, ret);
        sleep(1);

    }

    close(cfd);

    return 0;
}

实验现象

客户端向服务器发送10次hello,接收到服务器发来的10次大写HELLO;服务器首先打印IP地址和端口号,随后打印收到的10次由客户端传来的hello。

相关推荐
乌萨奇也要立志学C++2 小时前
【Linux】网络基础 从零理解网络通信:局域网、跨网传输与 Socket 预备知识
linux·服务器·网络
网络研究院3 小时前
Cloudflare 推出 Precursor 行为监测系统,全会话追踪技术引爆 AI 机器人防御战与隐私新争议
网络·人工智能·机器人·系统·cloudflare·反爬虫
RisunJan4 小时前
Linux命令-slabtop(实时显示内核 slab 缓存信息)
linux
Bruce_Liuxiaowei5 小时前
轻量级 IOC 管理方案:Streamlit 驱动的恶意IP情报平台
网络·jvm·网络协议·tcp/ip·安全
2601_965798476 小时前
Is Hygia Good for Maid & Janitorial Sites? Technical Audit
服务器·网络·数据库
蚰蜒螟6 小时前
从内核源码看Linux启动:chroot、execve与MS_MOVE的协奏曲
linux·服务器·网络
酷可达拉斯6 小时前
自动化运维-ansible配置文件与主机清单
linux·运维·自动化·ansible
影视飓风TIM7 小时前
Linux下C语言缓冲区原理 + Git版本控制
linux·c语言·git
来者皆善7 小时前
ZYNQ linux上使用 USB CDC ACM
linux·运维·服务器
☆凡尘清心☆8 小时前
CentOS Stream 9 专用 LNMP 全自动一键脚本
linux·运维·mysql·nginx·lnmp·centos stream 9