问题相关代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#define BUF_SIZE 1024
#define CONNECT_INFO 100
#define CLIENT_SIZE 100
int serv_port = 20000; //服务器端口号
pthread_mutex_t mutex; //互斥量
int clintQueue[CLIENT_SIZE]; //客户端fd环形队列
int front = 0, rear = 0; //客户端fd队列起始状态
void error_handle(char *message);
void *read_func(void *clnt_sock);
int send_message(int socketFd, char *message, int len);
/**
* @brief 打印错误信息
*
* @param message
*/
void error_handle(char *message)
{
perror(message);
exit(-1);
}
/**
* @brief 发送消息,成功返回1
*
* @param socketFd
* @param message
* @param len
* @return int
*/
int send_message(int socketFd, char *message, int len)
{
pthread_mutex_lock(&mutex);
int ret = write(socketFd, message, len);
if (ret <= 0)
{
perror("write error");
}
pthread_mutex_unlock(&mutex);
return ret <= 0 ? 0 : 1;
}
/**
* @brief 子线程读取客户端发送数据
*
* @param arg:客户端sockfd
* @return void*
*/
void *read_func(void *arg)
{
// pthread_detach(pthread_self());
int clnt_sock = *(int *)arg;
char buf[BUF_SIZE];
int message_len;
while ((message_len = read(clnt_sock, buf, BUF_SIZE)) != 0)
{
buf[message_len] = 0;
printf("%s", buf);
send_message(clnt_sock, buf, message_len - 1);
memset(buf, 0, BUF_SIZE);
}
pthread_mutex_lock(&mutex);
//客户端退出
printf("client %d[queue is %d]log out\n", clnt_sock, clintQueue[front]);
front++;
pthread_mutex_unlock(&mutex);
//会话结束断开连接
close(clnt_sock);
return NULL;
}
void *write_func(void *arg)
{
}
int main(int argc, char *argv[])
{
//返回客户端连接信息:文件描述符 + 地址 + 端口
char clientInfo[CONNECT_INFO];
int serv_sock, clnt_sock;
socklen_t clnt_addr_len;
pthread_t read_id; //线程id
struct sockaddr_in serv_addr, clnt_addr;
pthread_mutex_init(&mutex, NULL); //初始化互斥量
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock < 0)
{
perror("serv_sock create failed!");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(serv_port);
serv_addr.sin_addr.s_addr = INADDR_ANY;
// bind
if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
error_handle("bind fail");
}
else
{
puts("bind success");
}
if (listen(serv_sock, CLIENT_SIZE) < 0)
{
error_handle("listen fail");
}
else
{
puts("listen success");
}
while (1)
{
//主线程处理连接请求,子线程处理消息
clnt_addr_len = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
if (clnt_sock < 0)
{
puts("clnt_sock < 0");
close(clnt_sock);
}
//客户端队列满 入队失败
if (front == (rear + 1) % CLIENT_SIZE)
{
puts("client queue has flowed, connect failed");
close(clnt_sock);
}
else
{
//传递客户端的文件描述符交给子线程处理;
memset(clientInfo, 0, sizeof(clientInfo));
//客户端fd入队
pthread_mutex_lock(&mutex);
clintQueue[rear++] = clnt_sock;
pthread_mutex_unlock(&mutex);
// debug rear
printf("%d\n", rear);
puts("client queue add");
sprintf(clientInfo, "clientInfo[fd:%d, ip:%s, port:%d] has connected!", clnt_sock, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
puts(clientInfo);
pthread_create(&read_id, NULL, read_func, (void *)&clnt_sock);
pthread_detach(read_id);
printf("thread %ld create success!\n", (pthread_t)read_id);
//主线程主动分离子线程,使子线程结束后主动释放资源
}
}
close(serv_sock);
pthread_mutex_destroy(&mutex);
return 0;
}