当前位置:首页 > 行业动态 > 正文

c简单服务器

简单服务器用最少代码实现基本网络服务功能的服务器。

在网络编程中,使用C语言编写简单的服务器是一个基础且重要的任务,以下是关于如何用C语言编写简单服务器的详细介绍:

一、创建套接字

1、函数原型int socket(int domain, int type, int protocol)

2、参数说明

domain:指定协议族,常用的有AF_INET(IPv4)和AF_INET6(IPv6)。

type:指定套接字类型,常用的有SOCK_STREAM(流套接字,用于TCP)和SOCK_DGRAM(数据报套接字,用于UDP)。

protocol:通常为0,表示使用默认协议,对于TCP套接字,此参数应为0;对于UDP套接字,此参数也应为0。

3、示例代码

int server_fd = socket(AF_INET, SOCK_STREAM, 0);

这段代码创建了一个IPv4的TCP套接字,如果创建失败,会返回-1,可以通过perror()函数输出错误信息。

二、绑定套接字到端口

1、结构体定义:需要定义一个sockaddr_in结构体来存储服务器的地址信息。

2、设置结构体成员

sin_family:设置为AF_INET,表示使用IPv4地址。

sin_port:使用htons()函数将端口号转换为网络字节序后赋值给该成员,如果要绑定到8080端口,可以这样写:server_address.sin_port = htons(8080);

sin_addr.s_addr:可以设置为INADDR_ANY,表示监听所有可用的网络接口上的客户端请求。

3、绑定函数:使用bind()函数将套接字与指定的IP地址和端口号绑定。

int bind(int sockfd, struct sockaddr addr, socklen_t addrlen)

sockfd是之前创建的套接字描述符。

addr是指向包含有本机IP地址及端口号的sockaddr_in结构体的指针。

addrlen是地址结构体的长度,对于sockaddr_in结构体,其长度是sizeof(struct sockaddr_in)

bind(server_fd, (struct sockaddr)&server_address, sizeof(server_address));

三、监听连接请求

1、函数原型int listen(int sockfd, int backlog)

2、参数说明

c简单服务器

sockfd:已经绑定的套接字描述符。

backlog:指定在请求队列中允许的最大请求数,即最多允许多少个客户端连接到服务器但尚未处理。

3、示例代码

listen(server_fd, 5);

这行代码表示开始监听来自客户端的连接请求,最多允许5个客户端同时在请求队列中等待处理,如果监听失败,同样会返回-1,并可以使用perror()函数输出错误信息。

四、接受客户端连接

1、函数原型int accept(int sockfd, struct sockaddr cliaddr, socklen_t addrlen)

2、参数说明

sockfd:正在监听的套接字描述符。

cliaddr:指向一个sockaddr_in结构体,用于存储客户端的地址信息。

addrlen:是一个整型变量的地址,用于存储客户端地址结构体的长度。

3、示例代码

int client_fd = accept(server_fd, (struct sockaddr)&client_address, &client_addr_len);

当有客户端连接时,accept()函数会返回一个新的套接字描述符client_fd,用于与该客户端进行通信。client_address中会存储客户端的地址信息,client_addr_len中会存储客户端地址结构体的长度,如果没有客户端连接,accept()函数会阻塞等待,直到有客户端连接为止。

五、发送和接收数据

1、接收数据

函数原型ssize_t recv(int sockfd, void buf, size_t len, int flags)

c简单服务器

参数说明

sockfd:已连接的套接字描述符。

buf:指向接收数据的缓冲区。

len:缓冲区的长度。

flags:通常设置为0。

示例代码

char buffer[1024];

recv(client_fd, buffer, sizeof(buffer), 0);

这行代码从客户端接收数据并存储到buffer中。

2、发送数据

函数原型ssize_t send(int sockfd, const void buf, size_t len, int flags)

参数说明

sockfd:已连接的套接字描述符。

buf:指向要发送的数据缓冲区。

len:要发送的数据长度。

c简单服务器

flags:通常设置为0。

示例代码

send(client_fd, "Hello, Client!", strlen("Hello, Client!"), 0);

这行代码向客户端发送一段字符串"Hello, Client!"。

六、关闭套接字

1、关闭客户端套接字:当与客户端的通信完成后,需要关闭与客户端连接的套接字。

函数原型int close(int sockfd)

示例代码

close(client_fd);

这行代码关闭了与客户端连接的套接字。

2、关闭服务器套接字:在服务器程序结束前,也需要关闭监听套接字。

示例代码

close(server_fd);

这行代码关闭了服务器的监听套接字。

七、完整示例代码

以下是一个简单的C语言编写的服务器示例代码,它实现了上述功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8080
#define BACKLOG 5
#define BUFFER_SIZE 1024
int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_address, client_address;
    socklen_t client_addr_len = sizeof(client_address);
    char buffer[BUFFER_SIZE];
    ssize_t bytes_received;
    // 创建套接字
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    // 绑定套接字到端口
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(PORT);
    server_address.sin_addr.s_addr = INADDR_ANY;
    if (bind(server_fd, (struct sockaddr )&server_address, sizeof(server_address)) == -1) {
        perror("bind");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    // 监听连接请求
    if (listen(server_fd, BACKLOG) == -1) {
        perror("listen");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    printf("Server is listening on port %d...
", PORT);
    // 接受客户端连接并通信
    while (1) {
        client_fd = accept(server_fd, (struct sockaddr )&client_address, &client_addr_len);
        if (client_fd == -1) {
            perror("accept");
            continue;
        }
        printf("Client connected from %s:%d...
", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
        // 接收数据
        bytes_received = recv(client_fd, buffer, BUFFER_SIZE 1, 0);
        if (bytes_received == -1) {
            perror("recv");
            close(client_fd);
            continue;
        } else if (bytes_received == 0) {
            printf("Client disconnected.
");
            close(client_fd);
            continue;
        } else {
            buffer[bytes_received] = '