Socket-回声服务器

项目需求:

实现回声服务器的客户端/服务器程序,客户端通过网络连接到服务器,并发送任意一串英文信息,服务器端接收信息后,将每个字符转换为大写并回送给客户端显示。

Socket通信模型

服务器端

#include<stdio.h>           // 标准输入输出库
#include<unistd.h>          // 提供对 POSIX 操作系统 API 的访问功能,包含许多 POSIX 标准的函数原型
#include<sys/types.h>       // 包含一些基本的系统数据类型的定义
#include<string.h>          // 提供字符串操作函数
#include<ctype.h>           // 提供一些字符分类函数
#include<arpa/inet.h>       // 提供对IPv4地址转换函数的支持

#define SERVER_PORT 8888

int main(void)
{
    int sock;
    struct sockaddr_in server_addr;

    // 1. 创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 清空标签,写上地址和端口号
    bzero(&server_addr, sizeof(server_addr));

    // 3. 设置地址族为IPv4,监听本地所有IP地址,绑定端口号
    server_addr.sin_family = AF_INET;                   // 选择协议族IPV4
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    // 监听本地所有IP地址
    server_addr.sin_port = htons(SERVER_PORT);          // 绑定端口号

    // 4. 将套接字绑定到指定地址和端口
    bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // 5. 监听套接字,允许同时连接的最大客户端数为128
    listen(sock, 128);

    // 6. 打印等待客户端连接的提示信息
    printf("等待客户端的连接...\n");

    int done = 1;
    while (done)
    {
        struct sockaddr_in client;
        int client_sock;  
        int len = 0;
        char client_ip[64];
        char buf[256];

        socklen_t client_addr_len;
        client_addr_len = sizeof(client);
        
        // 接受客户端连接,返回客户端套接字描述符
        client_sock = accept(sock, (struct sockaddr *)&client, &client_addr_len);

        // 打印客户端地址和端口号
        printf("客户端IP: %s\t端口号: %d\n",
               inet_ntop(AF_INET, &client.sin_addr.s_addr, client_ip, sizeof(client_ip)),
               ntohs(client.sin_port));

        //读取客户端发送的数据
        len = read(client_sock, buf, sizeof(buf)-1);
        buf[len] = '\0';
        printf("receive[%d]: %s\n", len, buf);

        //转换成大写
        for(i=0; i<len; i++)
        {
            if(buf[i]>='a' && buf[i]<='z'){
                buf[i] = buf[i] - 32;
            }
            buf[i] = toupper(buf[i]);
        }

        len = write(client_sock, buf, len);


        printf("\nfinished. len: %d\n", len);
        
        // 关闭客户端套接字
        close(client_sock);
    }

    // 关闭服务器套接字
    close(sock);

    return 0;
}

struct sockaddr_in

是用于表示 IPv4 地址结构的结构体,在网络编程中经常用于指定套接字的地址信息。这个结构体在 <netinet/in.h> 头文件中定义。

struct sockaddr_in {
    short sin_family;           // 地址族 (Address Family),通常设置为 AF_INET
    unsigned short sin_port;    // 端口号,网络字节序
    struct in_addr sin_addr;    // IPv4 地址结构
    char sin_zero[8];           // 为了保持和 struct sockaddr 一样的大小,一般设置为 0
};
  • sin_family地址族,通常设置为 AF_INET 表示使用 IPv4 地址。
  • sin_port端口号,使用 unsigned short 类型表示,需要使用网络字节序(通过 htons 函数转换)。
  • sin_addrIPv4 地址结构,包含一个字段 s_addr 表示32位的IPv4地址,需要使用 htonl 函数进行转换。
  • sin_zero为了保持和 struct sockaddr 结构一样的大小而添加的字段,一般设置为0。

  1. sock = socket(AF_INET, SOCK_STREAM, 0);

    创建套接字,返回套接字描述符,并将其保存在 sock 变量中。使用IPv4地址族(AF_INET),流式套接字(SOCK_STREAM,即TCP),协议为默认(0)。
  2. bzero(&server_addr, sizeof(server_addr));

    清空 server_addr 结构体,确保其中的数据全部为零。
  3. bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));

    将套接字 sock 绑定到指定的地址和端口,使用 server_addr 结构体来指定。
  4. listen(sock, 128);

    开始监听套接字,允许同时连接的最大客户端数为128。
  5. printf("等待客户端的连接...\n");

    打印等待客户端连接的提示信息。

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SERVER_PORT 8888
#define SERVER_IP "192.168.65.129"

int main(int argc, char **argv) {
    int sockfd;
    char *message;
    struct sockaddr_in servaddr;
    int n;
    char buf[64];

    // 检查命令行参数
    if (argc != 2) {
        fputs("Usage: ./echo_client message \n", stderr);
        exit(1);
    }

    // 获取要发送的消息
    message = argv[1];

    printf("message: %s\n", message);

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 初始化服务器地址结构
    memset(&servaddr, '\0', sizeof(struct sockaddr_in));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
    servaddr.sin_port = htons(SERVER_PORT);

    // 连接到服务器
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    // 发送消息到服务器
    write(sockfd, message, strlen(message));

    // 从服务器接收响应
    n = read(sockfd, buf, sizeof(buf) - 1);

    if (n > 0) {
        buf[n] = '\0';
        printf("receive: %s\n", buf);
    } else {
        perror("error!!!");
    }

    printf("finished.\n");

    // 关闭套接字
    close(sockfd);

    return 0;
}

初步测试

1.运行服务器端

2.运行客户端 

在最新版本的Windows中,默认情况下并没有安装telnet客户端。

可以按照以下步骤来启用telnet客户端:

  1. 打开控制面板: 在Windows搜索栏中输入"Control Panel",然后打开控制面板。

  2. 进入程序: 在控制面板中,选择"程序",然后选择"启用或关闭Windows功能"。

  3. 启用Telnet客户端: 在弹出的窗口中,找到"Telnet客户端",勾选,然后确定。

  4. 等待安装完成: Windows会开始安装telnet客户端。安装完成,就可以再次尝试使用telnet命令。

客户端发送信息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值