socket回显服务器练习

前言

什么是回显服务器(echo server)呢?

回显服务器接收客户端发送的任何数据,并将这些数据原封不动地发送回客户端。回显服务器在连接成功的基础上只需要知道如何在客户端将收到的信息打印输出到控制台即可。我接下来会使用两种方法来输出,一种是printf(),另一种是fputs(),详见客户端信息传输部分。

服务端

c 复制代码
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#define PORT 8888
#define BUFFSIZE 1024
#define ERRORCODE -1

int main(int argc, char *argv[])
{
    char buf[BUFSIZ],client_addr_INFO[BUFFSIZE];
    int accept_fd, listen_fd;
    socklen_t client_len;
    struct sockaddr_in listen_addr, accept_addr;
    char buffer[BUFFSIZE];
    int buffer_len,i;
    int on = 1;
    //创建socket
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd == -1)
    {
        printf("创建socket error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    //bind
    if(setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))
    {
        printf("setsockopt error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    listen_addr.sin_family = AF_INET;
    listen_addr.sin_port = htons(PORT);
    listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(listen_fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0)
    {
        printf("bind error: %s \n", strerror(errno));
        return ERRORCODE;
    }

    //listen
    if (listen(listen_fd, 5) == -1)
    {
        printf("listen error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    printf("服务端创建成功,等待连接\n");
    //accept

    client_len = sizeof(accept_addr);
    
    /* code */
    accept_fd = accept(listen_fd, (struct sockaddr *)&accept_addr, &client_len);
    if (accept_fd == -1)
    {
        printf("accept error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    printf ("accept ip : %s,port : %d\n",
    inet_ntop(AF_INET,&accept_addr.sin_addr.s_addr,client_addr_INFO,sizeof(client_addr_INFO)),
    ntohs(accept_addr.sin_port));
    printf("accept ip : %s,port : %d\n",inet_ntoa(accept_addr.sin_addr),ntohs(accept_addr.sin_port));
   
    
    while (1)
    {
        memset(buffer,0,sizeof(buffer));
        buffer_len = read(accept_fd,buffer,sizeof(buffer));
        fputs(buffer,stdout);
     
        write(accept_fd,buffer,buffer_len);

        /* code */
    }
    
    close(accept_fd);
    close(listen_fd);
    return 0;
}

nc测试

在服务端做好了之后,我们先不急于写客户端,我们可以先用nc(netcat)工具来测试服务端是否可以正常运作。

先把服务端跑起来,然后在终端连接,可以看到回显是能够实现的。

客户端

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

#define BUFFSIZE 1024
#define ERRORCODE -1
#define PORT 8888
int main(int argc, char *argv[])
{
    
    char send_buffer[BUFFSIZE],recv_buffer[BUFFSIZE];
    
    int buffer_len;
    int client_fd;
    struct sockaddr_in connect_addr;
    //创建socket
    client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd == -1)
    {
        printf("socket error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    //connect

    inet_pton(AF_INET,"127.0.0.1",&connect_addr.sin_addr.s_addr);
    connect_addr.sin_family = AF_INET;
    connect_addr.sin_port = htons(PORT);
    if (connect(client_fd, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) == -1)
    {
        printf("connect error: %s \n", strerror(errno));
        return ERRORCODE;
    }
    printf("连接成功 , 请输入内容:\n");
    while (fgets(send_buffer,sizeof(send_buffer),stdin) != NULL)
    {
        
        write(client_fd,send_buffer,sizeof(send_buffer));
        //sleep(1);
        read(client_fd,recv_buffer,sizeof(recv_buffer));

        //fputs(recv_buffer,stdout);
        printf("回显内容: %s\n",recv_buffer);
        memset(send_buffer,0,sizeof(send_buffer));
        memset(recv_buffer,0,sizeof(recv_buffer));
        
    }
    close(client_fd);
    return 0;
}

运行效果


注:关于客户端与服务端连接的部分我在我的其它文章有写。

socket通信基本流程函数 -- 连接

相关推荐
Elastic 中国社区官方博客5 小时前
搜索倍增器:推动收入、生产力和 AI 实现规模化
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
光电的一只菜鸡5 小时前
ubuntu之坑(二十)——VMware虚拟机系统无法正常进入如何处理
linux·运维·ubuntu
青 春 记 忆6 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
Java王小怪7 小时前
Docker环境Redis没挂载保存数据
运维·docker·容器
保定公民7 小时前
达梦数据库存储过程中的数组类型详解:基础数组与记录数组的差异化应用
数据库·达梦·存储过程·达梦数据库·dm8·dm
你住过的屋檐7 小时前
【Nginx】linux上安装nginx
linux·运维·nginx
梦Arrebol8 小时前
Redis 内容及相关实验
数据库·redis
大模型码小白8 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
晓晓_za8986689 小时前
开源 GEO 优化源码二次开发:贴牌改造与业务模块扩展实践
java·运维·服务器·开发语言·性能优化·开源