用C++编写一个简单的基于TCP协议的网络程序

Posted 桃浪十七丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C++编写一个简单的基于TCP协议的网络程序相关的知识,希望对你有一定的参考价值。

相关函数

socket(int family, int type, int protocol);
bind(int sockfd, const struct sockaddr *server_addr, socklen_t addrlen);
listen(int sockfd, int backlog);
accept(int sockfd, struct sockaddr *client_addr, socklen_t addrlen);
connect (int fd, struct sockaddr *client_addr, socklen_t len);

服务端和客户端的流程应该如下


因此,

服务端的程序是这样的

int main() 
    int server_fd = -1;

    // 若server_fd 大于0,说明由之前的未断开的的TCP链接,得先断开
    if(server_fd > 0) 
        close(server_fd); server_fd = -1;
    

    // socket若成功则返回大于0的一个Tcp服务端的文件描述符
    // AF_INET是协议族,IPV4的,SOCK_STREAM就是指定TCP通信,若是UDP那就是SOCK_DGRAM了
    // 0是指协议的常值,一般是0,让系统根据前两个参数自己选
    if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1;

    // 处理SIGPIPE的做法取决于这个信号发生的时候想做什么,此处啥也不做,因此用SIG_IGN忽略掉信号
    signal(SIGPIPE, SIG_IGN);
    int opt = 1; unsigned int len = sizeof(opt);

    // setsockopt是对套接字做一些设置,设置为SO_REUSEADDR可以让IP地址复用,这是并发服务器的做法,可以有1<->n的效果
    // SOL_SOCKET是设置套接字级别,这里就是对套接字级别的选项进行设置
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, len);

    // 这一段就从IDE或者哪里找找源码可以自己看
    // htonl与htons是主机字节序转换为网络字节序,当时把这个和TCP三次握手的那个syn混淆了
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(19850);    // 随便写一个

    // bind也是成功返回0,失败返回-1
    if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
        return -1;

    // listen的返回值成功为0,失败为-1
    if(listen(server_fd, 5) != 0) return -1;

    struct sockaddr_in client_addr;
    memset(&client_addr, 0, sizeof(client_addr));
    int client_fd = -1;
    socklen_t socklen = 0;

    // 让服务程序可以一直运行,不至于执行一次就退出
    while (1) 
        // 成功则返回非负文件描述符
        // 此处要做一个从sockaddr_in到sockaddr的强制转换,点击源码能看到他们的关联,sockaddr_in把port与address分开
        if((client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &socklen)) < 0)
            return -1;

        // fork函数在父进程中返回子进程pid,在子进程返回0,由此判断是父还是子
        // fork出一个子进程,关闭子进程的监听文件描述符,关闭父进程处理业务的监听文件描述符
        // 就可以让父进程专心去响应客户端的访问请求,把业务逻辑处理交给子进程
        if(fork() > 0) 

            // 关闭父进程对客户端的文件描述符
            close(client_fd); client_fd = -1;
            continue;
        
        // 关闭父进程对子进程的服务端文件描述符
        close(server_fd); server_fd = -1;

        // TODO
        char send_buffer[] = "Hello TcpClient!";

        // 发送给客户端
        write(client_fd, send_buffer, sizeof(send_buffer));
    
    return 0;

客户端程序是这样的

int main() 
    int client_fd = -1;
    // socket返回的值与server中socket返回值一个意思
    client_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in client_addr;
    client_addr.sin_family = AF_INET;
    client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    client_addr.sin_port = htons(19850);

    // 成功返回0,失败返回-1
    connect(client_fd, (struct sockaddr *)&client_addr, sizeof(client_addr));

    char recv_buffer[31];
    // TODO
    memset(recv_buffer, 0, sizeof(recv_buffer));

    read(client_fd, recv_buffer, sizeof(recv_buffer));
    printf("Received: %s", recv_buffer);
    return 0;

以上是关于用C++编写一个简单的基于TCP协议的网络程序的主要内容,如果未能解决你的问题,请参考以下文章

用C++编写一个简单的基于TCP协议的网络程序

用C++编写一个简单的基于TCP协议的网络程序

C++语言实现网络聊天程序的设计与实现(基于TCP/IP协议的SOCKET编程)超详细(代码+解析)

网络协议分析课程设计:基于TCP协议网上聊天程序

怎么用C或C++来编写一个抓包程序,或者是编写一个能够保存抓出的包然后分析出结果的程序,要个思路!

099 基于TCP协议的socket