多线程并发服务器
模型
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() {
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"
#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;
}