TCP echo_server(C++)回射服务器实现以及问题记录

TCP echo_server(C++)回射服务器实现以及问题记录

基本运行方式:

  1. 客户端接收用户输入的字符串并发送到服务器端
  2. 服务器端将接收的字符串数据传回客户端
  3. 服务器端和客户端之间的字符串回射一直执行到客户端输入Q为止

服务器端实现:

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

const int buf_size = 1024;
void error_handler(std::string message);

int main(int argc, char* argv[])
{
    int serv_sock, clt_sock;
    char message[buf_size];
    int str_len, i;

    struct sockaddr_in serv_adr,clt_adr;
    socklen_t clt_adr_len;
    if(argc != 2)
    {
        printf("usage %s <IP> <port>", argv[0]);
        exit(1);
    }

    // const char* ip = argv[1];
    // int port = atoi(argv[2]);

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1)
        error_handler("socket() error");
    memset(&serv_adr, 0, sizeof serv_adr);
    memset(&clt_adr, 0, sizeof(clt_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htons(INADDR_ANY);
    //serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_adr.sin_port = htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)
        error_handler("bind() error");
    if(listen(serv_sock, 5) == -1)
        error_handler("listen() error");
    clt_adr_len = sizeof(clt_sock);
    
    // for(int i=0;i<5;++i)
    // {
    //     clt_sock = accept(serv_sock, (struct sockaddr*)&clt_adr, &clt_adr_len);
    //     if(clt_sock == -1)
    //         error_handler("accept() error");
    //     else
    //         printf("Connnected client %d. \n", i+1);
    //     while((str_len = read(clt_sock, message, buf_size)) != 0)
    //         write(clt_sock, message, str_len);
    //     close(clt_sock);
    // }

    printf("accept........\n");
    clt_sock = accept(serv_sock, (struct sockaddr*)&clt_adr, &clt_adr_len);
    if(clt_sock == -1)
        error_handler("accept() error");
    else
        printf("accept success\n");
    while((str_len = read(clt_sock, message, buf_size)) != 0)
        write(clt_sock, message, str_len);
    close(clt_sock);

    close(serv_sock);
    return 0;
}

void error_handler(std::string message)
{
    fputs(message.c_str(), stderr);
    fputc('\n', stderr);
    exit(1);
}

客户端实现:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <memory.h>

const int buf_size = 1024;
void error_handler(std::string message);

int main(int argc, char* argv[])
{
    int sock;
    char message[buf_size];
    int str_len;
    int recv_len, recv_cnt;
    struct sockaddr_in serv_adr;
    socklen_t clt_adr_len;
    if(argc != 3)
    {
        printf("usage %s <IP> <port>", argv[0]);
        exit(1);
    }
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1)
        error_handler("socket() error");
    memset(&serv_adr, 0, sizeof serv_adr);
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_adr.sin_port = htons(atoi(argv[2]));

    if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)
        error_handler("connect() error");
    else
        puts("Connected............");
    while(1)
    {
        fputs("Input message (Q to quit) : ", stdout);
        fgets(message, buf_size, stdin);
        if(!strcmp(message, "q\n")||!strcmp(message, "Q\n"))
            break;
        str_len = write(sock, message, strlen(message));
        //str_len = read(sock, message, buf_size - 1);
        recv_len = 0;
        while(recv_len < str_len)
        {
            recv_cnt = read(sock, &message[recv_len], buf_size - 1);
            if(recv_cnt == -1)
                error_handler("read() error");
            recv_len += recv_cnt;
        }
        message[str_len] = 0;
        printf("Message from server : %s", message);
    }

    close(sock);
    return 0;
}

void error_handler(std::string message)
{
    fputs(message.c_str(), stderr);
    fputc('\n', stderr);
    exit(1);
}

运行结果:

在tty1上运行服务器端程序tty1
在tty2上运行客户端程序
tty2

遇到的问题:

服务器端正常监听,客户端连接失败,connect( ) 返回 -1

解决:
使用tcpdump抓包,显示连接请求被拒绝,查看代码并没有发现明显错误,怀疑是端口没有被使用。
所以查看当前进程占用的是哪个端口:

$ netstat -anp

发现服务器端口正常监听,但是端口不是8000,而是52053,这意味着操作系统随机分配了一个端口,而并未使用指定的端口8000
查看服务器端代码,发现htonl( )函数使用错误,应该使用htons( )函数(程序内已经和改正)
因为ubuntu使用的是小端字节序,而使用htonl函数时,进行32位转换,所以htonl(8000)结果为0。

使用htons()就可以解决

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值