0621作业

多线程并发服务器

模型

sfd = socket();
bind();
listen();
while(1){
    newfd = accept();
    pthread_create(&tid, NULL, do_cli_msg, [newfd, cin]集合);
    pthread_detach(tid);
}
close(sfd);

void* do_cli_msg(void* arg){
    while(1){
        recv();
        send();    
    }
    close(newfd);
}

服务器实现

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

#define PORT 8080
#define IP "192.168.124.38"
#define MAX_CLIENTS 5
#define BUFFER_SIZE 1024

void *handle_client(void *arg);
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
fd_set readfds;

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

    // 设置端口复用
    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 = IP;
    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, MAX_CLIENTS) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("服务器端口:%d...\n", PORT);

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

        // 为新连接创建线程
        pthread_t client_thread;
        if(pthread_create(&client_thread, NULL, handle_client, (void*) &new_socket) < 0){
            perror("create thread");
            exit(EXIT_FAILURE);
        }

        // 分离线程,防止资源泄漏
        pthread_detach(client_thread);
    }

    return 0;
}

void* handle_client(void* arg){
    int sock = *((int*)arg);

    char client_message[BUFFER_SIZE];
    while(1) {
        memset(client_message, 0, sizeof(client_message));
        valread = read(sock , client_message, BUFFER_SIZE);
        if(valread <= 0){
            // 发生错误或客户端关闭连接
            break;
        }

        printf("Client %d says: %s\n", sock, client_message);

        // 处理客户端消息并准备响应
        char *response = "服务器已就绪\n";
        send(sock , response , strlen(response) , 0 );
    }

    close(sock);
    printf("关闭socket: %d\n", sock);
    pthread_exit(NULL);

}

select的TCP服务器

模型

sfd = socket();
bind();
listen();
while(1){
    tempfds = readfds;
    select(maxfd+1, &tempfds, NULL, NULL, NULL);
    for(int i=0; i<=maxfd; i++){
        if(FD_ISSET(i, &temfds) == 0)     continue;
        if(0 == i){                    
        }          
        else if(sfd == i){
            newfd=accept()
            FD_SET(newfd, &readfds);
            maxfd=newfd>maxfd?newfd:maxfd;        
        }   
        else{
            res=recv(i,  );
            if(0 == res){
                FD_CLR(i, &readfds);
                close(i);
                while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->0);            
            }
            send(i,  );        
        }           
    }
}
close(sfd);

服务器实现

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

#define PORT 12345 

int main() {
    int listenfd, newfd, maxfd, i, j, nbytes;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addrlen;
    char buffer[1024];
    fd_set master_set, read_fds;

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = 192.168.124.38;
    memset(&(server_addr.sin_zero), '\0', 8);

    if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        close(listenfd);
        exit(1);
    }

    if (listen(listenfd, 10 ) == -1) {
        perror("listen");
        close(listenfd);
        exit(1);
    }

    FD_ZERO(&master_set);
    FD_ZERO(&read_fds);
    FD_SET(listenfd, &master_set);
    maxfd = listenfd;

    while (1) {
        read_fds = master_set;

        if (select(maxfd + 1, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(1);
        }

        for (i = 0; i <= maxfd; i++) {
            if (FD_ISSET(i, &read_fds)) {
                if (i == listenfd) {
                    addrlen = sizeof(client_addr);
                    if ((newfd = accept(listenfd, (struct sockaddr *)&client_addr, &addrlen)) == -1) {
                        perror("accept");
                    } else {
                        FD_SET(newfd, &master_set);
                        if (newfd > maxfd) {
                            maxfd = newfd;
                        }
                        printf("New connection from %s on socket %d\n", inet_ntoa(client_addr.sin_addr), newfd);
                    }
                } 
                else {
                    if ((nbytes = recv(i, buffer, sizeof(buffer), 0)) <= 0) {
                        if (nbytes == 0) {
                            printf("Socket %d hung up\n", i);
                        } else {
                            perror("recv");
                        }
                        close(i);
                        FD_CLR(i, &master_set);
                    } else {
                        for (j = 0; j < nbytes; j += 0) {
                            int sent = send(i, buffer + j, nbytes - j, 0);
                            if (sent == -1) {
                                perror("send");
                                close(i);
                                FD_CLR(i, &master_set);
                                break;
                            }
                            j += sent;
                        }
                    }
                }
            }
        }
    }

    close(listenfd);
    return 0;
}


select的TCP客户端

实现

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

#define SERVER_IP "127.0.0.1"  // 服务器 IP 地址
#define SERVER_PORT 12345      // 服务器端口

int main() {
    int sockfd, maxfd, nbytes;
    struct sockaddr_in server_addr;
    fd_set read_fds;
    char buffer[1024];

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

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    memset(&(server_addr.sin_zero), '\0', 8);

    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect");
        exit(1);
    }

    printf("Connected to server on socket %d\n", sockfd);

    while (1) {
        FD_ZERO(&read_fds);
        FD_SET(sockfd, &read_fds);
        FD_SET(STDIN_FILENO, &read_fds);
        maxfd = (sockfd > STDIN_FILENO ? sockfd : STDIN_FILENO) + 1;

        if (select(maxfd, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(1);
        }

        if (FD_ISSET(STDIN_FILENO, &read_fds)) {
            if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
                break;
            }
            nbytes = strlen(buffer);
            if (send(sockfd, buffer, nbytes, 0) == -1) {
                perror("send");
                exit(1);
            }
        }

        if (FD_ISSET(sockfd, &read_fds)) {
            if ((nbytes = recv(sockfd, buffer, sizeof(buffer), 0)) <= 0) {
                if (nbytes == 0) {
                    printf("Server hung up\n");
                } else {
                    perror("recv");
                }
                break;
            } else {
                printf("Received from server: %.*s", nbytes, buffer);
            }
        }
    }

    close(sockfd);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值