linux多线程搭建服务器

服务端

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

#define PORT 8080
#define BUFFER_SIZE 1024

void *connection_handler(void *socket_desc) {
int sock = *(int *)socket_desc;
char buffer[BUFFER_SIZE] = {0};
char *response = “HTTP/1.1 200 OK\nContent-Type: text/html\n\n

Hello, World!

\n”;

read(sock, buffer, BUFFER_SIZE);
printf("Received request:\n%s\n", buffer);

write(sock, response, strlen(response));
close(sock);

free(socket_desc);

return NULL;

}

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

// Create socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("socket failed");
    exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Bind socket to localhost:PORT
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("bind failed");
    exit(EXIT_FAILURE);
}

// Listen for incoming connections
if (listen(server_fd, 3) < 0) {
    perror("listen failed");
    exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);

// Accept incoming connections and handle them using threads
while (1) {
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
        perror("accept failed");
        exit(EXIT_FAILURE);
    }

    printf("Connection accepted\n");

    pthread_t thread;
    int *new_sock = malloc(1);
    *new_sock = new_socket;

    if (pthread_create(&thread, NULL, connection_handler, (void *)new_sock) < 0) {
        perror("could not create thread");
        return 1;
    }

    // Detach the thread, so it will clean up after itself
    pthread_detach(thread);
}

return 0;

}

完善客户请求处理

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

#define PORT 8080
#define BUFFER_SIZE 1024

void send_response(int socket, int status, char* content_type, char* content) {
char response[BUFFER_SIZE] = {0};
char headers[BUFFER_SIZE] = {0};

sprintf(headers, "HTTP/1.1 %d ", status);
switch(status) {
    case 200:
        strcat(headers, "OK\r\n");
        break;
    case 404:
        strcat(headers, "Not Found\r\n");
        break;
    default:
        strcat(headers, "Internal Server Error\r\n");
}

sprintf(response, "%sContent-Type: %s\r\n\r\n%s", headers, content_type, content);
send(socket, response, strlen(response), 0);

}

void handle_request(int new_socket) {
char buffer[BUFFER_SIZE] = {0};
char method[10], path[255], protocol[20];

read(new_socket, buffer, BUFFER_SIZE);
sscanf(buffer, "%s %s %s", method, path, protocol);

if(strcmp(method, "GET") == 0) {
    char file_path[255] = {0};
    sprintf(file_path, ".%s", path);
    
    // Open requested file
    int fd = open(file_path, O_RDONLY);
    if(fd == -1) {
        send_response(new_socket, 404, "text/html", "<h1>404 Not Found</h1>");
    } else {
        struct stat file_stat;
        fstat(fd, &file_stat);
        char* content_type = "text/html";
        if (strstr(file_path, ".png")) content_type = "image/png";
        if (strstr(file_path, ".jpg")) content_type = "image/jpeg";
        if (strstr(file_path, ".gif")) content_type = "image/gif";
        if (strstr(file_path, ".html")) content_type = "text/html";

        char* content = malloc(file_stat.st_size);
        read(fd, content, file_stat.st_size);
        send_response(new_socket, 200, content_type, content);
        free(content);
    }
} else {
    send_response(new_socket, 500, "text/html", "<h1>500 Internal Server Error</h1>");
}

close(new_socket);

}

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Binding socket to the specified port
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

// Listening for incoming connections
if (listen(server_fd, 3) < 0) {
    perror("Listen failed");
    exit(EXIT_FAILURE);
}

printf("Server listening on port %d\n", PORT);

// Accept incoming connections
while (1) {
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // Handle incoming request
    handle_request(new_socket);
}

return 0;

}

第三版

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

#define PORT 8080
#define BUFFER_SIZE 1024

void send_response(int socket, int status, char* content_type, char* content) {
char response[BUFFER_SIZE] = {0};
char headers[BUFFER_SIZE] = {0};

sprintf(headers, "HTTP/1.1 %d ", status);
switch(status) {
    case 200:
        strcat(headers, "OK\r\n");
        break;
    case 404:
        strcat(headers, "Not Found\r\n");
        break;
    default:
        strcat(headers, "Internal Server Error\r\n");
}

sprintf(response, "%sContent-Type: %s\r\n\r\n%s", headers, content_type, content);
send(socket, response, strlen(response), 0);

}

void* handle_request(void* socket_ptr) {
int new_socket = ((int) socket_ptr);
char buffer[BUFFER_SIZE] = {0};
char method[10], path[255], protocol[20];

read(new_socket, buffer, BUFFER_SIZE);
sscanf(buffer, "%s %s %s", method, path, protocol);

if(strcmp(method, "GET") == 0) {
    char file_path[255] = {0};
    sprintf(file_path, ".%s", path);
    
    // Open requested file
    int fd = open(file_path, O_RDONLY);
    if(fd == -1) {
        send_response(new_socket, 404, "text/html", "<h1>404 Not Found</h1>");
    } else {
        struct stat file_stat;
        fstat(fd, &file_stat);
        char* content_type = "text/html";
        if (strstr(file_path, ".png")) content_type = "image/png";
        if (strstr(file_path, ".jpg")) content_type = "image/jpeg";
        if (strstr(file_path, ".gif")) content_type = "image/gif";
        if (strstr(file_path, ".html")) content_type = "text/html";

        char* content = malloc(file_stat.st_size);
        read(fd, content, file_stat.st_size);
        send_response(new_socket, 200, content_type, content);
        free(content);
    }
} else {
    send_response(new_socket, 500, "text/html", "<h1>500 Internal Server Error</h1>");
}

close(new_socket);
free(socket_ptr);
return NULL;

}

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Binding socket to the specified port
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

// Listening for incoming connections
if (listen(server_fd, 3) < 0) {
    perror("Listen failed");
    exit(EXIT_FAILURE);
}

printf("Server listening on port %d\n", PORT);

// Accept incoming connections and handle in separate threads
while (1) {
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // Create a new thread to handle the client
    pthread_t thread;
    int* socket_ptr = malloc(sizeof(int));
    *socket_ptr = new_socket;
    if (pthread_create(&thread, NULL, handle_request, (void*) socket_ptr) != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    pthread_detach(thread);  // Detach the thread to avoid memory leaks
}

return 0;

}

修改

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

#define PORT 12345
#define MAX_BUFFER_SIZE 1024

void send_data(int sockfd, const char *data) {
size_t total_sent = 0;
size_t data_len = strlen(data);

while (total_sent < data_len) {
    ssize_t sent = send(sockfd, data + total_sent, data_len - total_sent, 0);
    if (sent == -1) {
        perror("send");
        exit(EXIT_FAILURE);
    }
    total_sent += sent;
}

}

int main() {
int sockfd;
struct sockaddr_in server_addr;
const char *content = “This is the content to be sent to the socket.”;

// 创建socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(EXIT_FAILURE);
}

// 设置server_addr结构
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  // 替换为目标服务器的IP地址

// 连接到服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
    perror("connect");
    exit(EXIT_FAILURE);
}

// 发送数据
send_data(sockfd, content);

// 关闭socket
close(sockfd);

return 0;

}

加入post处理

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

#define PORT 8080
#define MAX_THREADS 5

void *connection_handler(void *socket_desc);

int main() {
int server_fd, new_socket, c;
struct sockaddr_in address, client_addr;
int opt = 1;
int addrlen = sizeof(address);

// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("socket failed");
    exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
    perror("setsockopt");
    exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Bind the socket to localhost port 8080
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
    perror("bind failed");
    exit(EXIT_FAILURE);
}

// Try to specify maximum of 3 pending connections for the master socket
if (listen(server_fd, 3) < 0) {
    perror("listen");
    exit(EXIT_FAILURE);
}

printf("Server listening on port %d...\n", PORT);

// Accept incoming connections
while ((new_socket = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t*)&addrlen))) {
    pthread_t thread;
    int *new_sock = malloc(1);
    *new_sock = new_socket;
    
    if (pthread_create(&thread, NULL, connection_handler, (void*)new_sock) < 0) {
        perror("could not create thread");
        return 1;
    }
    
    // Now join the thread, so that we don't terminate before the thread
    pthread_join(thread, NULL);
}

if (new_socket < 0) {
    perror("accept failed");
    return 1;
}

return 0;

}

void *connection_handler(void *socket_desc) {
// Get the socket descriptor
int sock = (int)socket_desc;
int read_size;
char client_message[1024];
char response[1024] = “HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n

Hello, World!

”;

// Receive a message from client
read_size = recv(sock, client_message, 1024, 0);
if (read_size > 0) {
    // Send the message back to client
    write(sock, response, strlen(response));
}

free(socket_desc);
close(sock);
pthread_exit(NULL);

}

post请求处理

void *connection_handler(void *socket_desc) {
// Get the socket descriptor
int sock = (int)socket_desc;
int read_size;
char client_message[1024];
char response[1024];

// Receive a message from client
read_size = recv(sock, client_message, 1024, 0);
if (read_size > 0) {
    // Parse HTTP request to get method and URI
    char method[10], uri[50];
    sscanf(client_message, "%s %s", method, uri);
    
    // Check if it's a POST request
    if (strcmp(method, "POST") == 0) {
        // Find where the POST data begins
        char *data_start = strstr(client_message, "\r\n\r\n");
        if (data_start) {
            // Move to actual data
            data_start += 4;
            
            // Example: Parse POST data (here assuming it's form-urlencoded)
            char post_data[1024];
            sscanf(data_start, "%s", post_data);
            
            // Generate a response based on received data
            sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World! This is a POST request</h1><p>Received data: %s</p></body></html>", post_data);
        } else {
            // Malformed POST request (no data found)
            sprintf(response, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nBad Request");
        }
    } else {
        // Handle other HTTP methods (not implemented in this example)
        sprintf(response, "HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/plain\r\n\r\nMethod Not Allowed");
    }
    
    // Send the message back to client
    write(sock, response, strlen(response));
}

free(socket_desc);
close(sock);
pthread_exit(NULL);

}

传输图像

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

#define PORT 8080
#define BUFFER_SIZE 1024

void send_image(int client_socket, const char *filename) {
FILE *fp = fopen(filename, “rb”);
if (fp == NULL) {
perror(“Error opening file”);
return;
}

fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
rewind(fp);

// 构建 HTTP 头部
char header[BUFFER_SIZE];
snprintf(header, sizeof(header),
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: image/jpeg\r\n"
    "Content-Length: %ld\r\n\r\n", file_size);

// 发送 HTTP 头部
send(client_socket, header, strlen(header), 0);

// 发送图像数据
char buffer[BUFFER_SIZE];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, fp)) > 0) {
    send(client_socket, buffer, bytes_read, 0);
}

fclose(fp);

}

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

// 创建 socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// 绑定地址和端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

// 监听连接
if (listen(server_fd, 10) < 0) {
    perror("Listen failed");
    exit(EXIT_FAILURE);
}

printf("Server listening on port %d\n", PORT);

while (1) {
    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // 接收客户端请求
    char buffer[BUFFER_SIZE] = {0};
    read(new_socket, buffer, BUFFER_SIZE);

    // 提取请求中的文件名
    char *filename = "example.jpg"; // 修改为实际的图片文件名
    printf("Requested file: %s\n", filename);

    // 发送图片
    send_image(new_socket, filename);

    // 关闭连接
    close(new_socket);
}

return 0;

}

使用文件描述符

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

#define PORT 8080
#define BUFFER_SIZE 1024

void send_image(int client_fd, const char *filename) {
int file_fd = open(filename, O_RDONLY);
if (file_fd < 0) {
perror(“Error opening file”);
return;
}

// 获取文件大小
off_t file_size = lseek(file_fd, 0, SEEK_END);
lseek(file_fd, 0, SEEK_SET);

// 构建 HTTP 头部
char header[BUFFER_SIZE];
snprintf(header, sizeof(header),
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: image/jpeg\r\n"
    "Content-Length: %ld\r\n\r\n", (long)file_size);

// 发送 HTTP 头部
write(client_fd, header, strlen(header));

// 发送图像数据
char buffer[BUFFER_SIZE];
ssize_t bytes_read;
while ((bytes_read = read(file_fd, buffer, BUFFER_SIZE)) > 0) {
    write(client_fd, buffer, bytes_read);
}

close(file_fd);

}

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

// 创建 socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// 绑定地址和端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

// 监听连接
if (listen(server_fd, 10) < 0) {
    perror("Listen failed");
    exit(EXIT_FAILURE);
}

printf("Server listening on port %d\n", PORT);

while (1) {
    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // 接收客户端请求
    char buffer[BUFFER_SIZE] = {0};
    read(new_socket, buffer, BUFFER_SIZE);

    // 提取请求中的文件名
    char *filename = "example.jpg"; // 修改为实际的图片文件名
    printf("Requested file: %s\n", filename);

    // 发送图片
    send_image(new_socket, filename);

    // 关闭连接
    close(new_socket);
}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值