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通信基本流程函数 -- 连接

相关推荐
java_logo7 分钟前
2025 最新 Docker 镜像源加速列表与使用指南(10月更新)
运维·docker·容器
蛐蛐蛐7 分钟前
Win11上VS Code免输密码连接Ubuntu的正确设置方法
linux·运维·ubuntu
YongCheng_Liang31 分钟前
锐捷无线控制器基础配置
运维·网络
荣光波比1 小时前
Ansible(三)—— 使用Ansible自动化部署LNMP环境实战指南
运维·自动化·云计算·ansible
七七七七071 小时前
【Linux 系统】理解Linux下一切皆文件
linux·运维·服务器
启明真纳1 小时前
PostgreSQL 单库备份
数据库·postgresql
Amd7941 小时前
PostgreSQL备份不是复制文件?物理vs逻辑咋选?误删还能精准恢复到1分钟前?
数据库·postgresql
tjsoft1 小时前
专栏丨华为HN8145XR光猫获取超级管理员密码
运维·服务器·网络
wzg20161 小时前
pyqt5 简易入门教程
开发语言·数据库·qt
盛满暮色 风止何安2 小时前
网络安全设备 防火墙
服务器·网络·网络协议·计算机网络·安全·web安全·网络安全