用C++写一个简单的服务器(Linux)

17 篇文章 1 订阅
11 篇文章 1 订阅

用C++写一个简单的服务器(Linux)

下面是创建一个简单服务器的基本流程,所用的端口是8099。后面贴了代码。

一、基本流程:
  1. 创建套接字
  2. 配置服务器地址相关参数
  3. 将两者绑定
  4. 监听套接字上的端口
  5. 在上面创建的套接字上等待连接,并打开一个新的套接字用于与请求之间的交互
  6. 在发送缓冲区中写入响应
  7. 关闭连接
  1. 创建套接字
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0){
    std::cout << "create socketfd failed" <<std::endl;
    return 0;
}

函数socket()所在的头文件sys/socket.h,声明为
extern int socket (int __domain, int __type, int __protocol) __THROW;

  1. 配置服务器地址相关参数
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);

变量servaddr类型struct sockaddr_in,它所在的头文件netinet/in.h

  1. 将上面两者绑定
int bind_ok = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if(bind_ok < 0){
    std::cout << "bind socket with server address  failed" <<std::endl;
    return 0;
}

函数bind()所在的头文件sys/socket.h,声明为
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW;

  1. 监听套接字上的端口
int listen_ok = listen(listenfd, LISTENQ);
if(listen_ok < 0){
    std::cout << "listen socket  failed" <<std::endl;
    return 0;
}

函数listen()所在的头文件sys/socket.h,声明为
extern int listen (int __fd, int __n) __THROW;

  1. 在上面创建的套接字上等待连接,并打开一个新的套接字用于与请求之间的交互
connfd = accept(listenfd, NULL, NULL);
if(connfd < 0){
    std::cout << "create connection socket failed" <<std::endl;
    return 0;
}

函数accept()所在的头文件sys/socket.h,声明为
extern int accept (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len);

  1. 在发送缓冲区中写入响应
write_ok = write(connfd, buffer.c_str(), strlen(buffer.c_str()));
if(write_ok < 0){
    std::cout << "write info to connection socket failed" <<std::endl;
    close(connfd);
    return 0;
}

函数 write()所在的头文件unistd.h,声明为
extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;

函数close()所在的头文件unistd.h,声明为
extern int close (int __fd);

  1. 关闭连接
close(connfd);
二、编译、运行、验证
$ # 编译
$ g++ simple_server.cpp -o run_this
$ # 运行
$ ./run_this
$ # 打开一个新的shell窗口,然后执行下面的命令
$ curl http://localhost:8099
$ # 执行后,新的shell窗口会有如下的显示结果:
hello, this is a simple server.
$ # 运行 run_this 的窗口中,当服务器接收到请求之后,会显示如下的结果:
hello, this is a simple server.

length of it: 32

三、代码
#include <iostream>     // std::cout、std::endl
#include <sys/socket.h> // socket、bind、listen、accept
#include <netinet/in.h> // htonl、htons
#include <unistd.h>     // write、close
#include <string.h>     // bzero
#define PORT 8099
#define LISTENQ 5
int main(){
    /* 准备重要参数 */
    // 结构体 sockaddr_in 位于 netinet/in.h
    int listenfd, connfd;
    struct sockaddr_in servaddr;
    
    /* 创建套接字 */
    // 常量 AF_INET 位于 bits/socket.h,经由 sys/socket.h 导入
    // 常量 SOCK_STREAM 位于 bits/socket_type.h,先后经由 bits/socket.h、sys/socket.h 导入
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(listenfd < 0){
        std::cout << "create socketfd failed" <<std::endl;
        return 0;
    }

    /* 准备地址端口信息 */
    // 常量 INADDR_ANY 位于 netinet/in.h
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);
    
    /* 绑定套接字与地址端口 */
    int bind_ok = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if(bind_ok < 0){
        std::cout << "bind socket with server address  failed" <<std::endl;
        return 0;
    }
    
    /* 监听端口 */
    int listen_ok = listen(listenfd, LISTENQ);
    if(listen_ok < 0){
        std::cout << "listen socket  failed" <<std::endl;
        return 0;
    }
    
    /* 准备这个简单服务器返回的信息 */
    std::string buffer = "hello, this is a simple server.\n";
    int write_ok; // 用于判断是否成功将数据写入发送缓存
    // 循环等待
    while(1){
    	// 监听到有请求,创建交互的套接字
        connfd = accept(listenfd, NULL, NULL);
        if(connfd < 0){
            std::cout << "create connection socket failed" <<std::endl;
            return 0;
        }
        std::cout << buffer << std::endl << "length of it: " << buffer.size()<< std::endl;
        
        // 将响应的数据写入发送缓冲区
        write_ok = write(connfd, buffer.c_str(), strlen(buffer.c_str()));
        if(write_ok < 0){
            std::cout << "write info to connection socket failed" <<std::endl;
            close(connfd); // 关闭连接
            return 0;
        }
        // 关闭连接
        close(connfd);
    }
}
  • 5
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值