#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define TYPE_VER 8001
typedef struct tag_tk {
int g_connfd;
char name[100];
} TK;
TK tk[100] = {};
void sigint (int signum) {
printf ("聊天服务器即将关闭...\n");
int i = 0;
for (i = 0; i < 100; i++) {
close (tk[i].g_connfd);
}
exit (0);
}
// TCP服务器向所有客户端发送接收到的内容
void sendall (int num, char buf[], int size) {
int i = 0;
for (i = 0; i < 100; i++) {
if (tk[i].g_connfd == 0 || num == i) {
continue;
}
if (send (tk[i].g_connfd, buf, size, 0) == -1) {
perror ("Error->send:");
//break;
}
// printf ("发送了一次 i:%d\n", i);
}
}
// TCP服务器初始化 传入指定端口 准备通信之前的各自数据,绑定并监听,返回监听的套接字描述符
int init (unsigned short type) {
int sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror ("Error->socket");
return -1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons (type);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1) {
perror ("Error->bind");
return -1;
}
if (listen (sockfd, 1024) == -1) {
perror ("Error->listen");
return -1;
}
return sockfd;
}
void* thread_proc (void* arg) {
pthread_detach (pthread_self ());
char req[1024];
int i = (int)arg;
for (;;) {
while (! strlen (tk[i].name)) {
ssize_t rb = recv (tk[i].g_connfd, tk[i].name, sizeof (tk[i].name), 0);
if (rb == -1) {
perror ("Error-<recv");
continue;
}
printf ("%s :加入会话! i:%d\n", tk[i].name, i);
}
ssize_t rb = recv (tk[i].g_connfd, req, sizeof (req), 0);
if (rb == -1) {
perror ("Error-<recv");
continue;
}
if (rb == 0) {
printf ("%s : 退出会话!\n", tk[i].name);
break;
}
// printf ("%s>:%s\n", tk[i].name, req);
sendall (i, req, rb);
/*
if (send (tk[i].g_connfd, req, sizeof (rb), 0) == -1) {
perror ("Error->send");
break;
}
*/
// 服务器接收到客户端的消息,再次转发给所有的在线客户端
}
close (tk[i].g_connfd);
tk[i].g_connfd = 0;
return NULL;
}
// TCP服务器接收聊天内容
int rcvreq (int sockfd) {
int i = 0;
for (;;) {
for (i = 0; i < 100; i++) {
if (tk[i].g_connfd == 0) {
break;
}
}
struct sockaddr_in addrcli = {};
socklen_t addrlen = sizeof (addrcli);
if ((tk[i].g_connfd = accept (sockfd, (struct sockaddr*)&addrcli, &addrlen)) == -1) {
perror ("Error->accept");
printf ("sockfd:%d\n", sockfd);
}
pthread_t tid;
printf ("客户端:%s 请求加入会话! i:%d\n", inet_ntoa (addrcli.sin_addr), i);
pthread_create (&tid, NULL, thread_proc, (void*)i);
}
return 0;
}
int main (void) {
if (signal (SIGINT, sigint) == SIG_ERR) {
perror ("Error->sigint");
return -1;
}
int g_sockfd = -1;
if ((g_sockfd = init (TYPE_VER)) == -1) {
return -1;
}
printf ("聊天室服务器准备就绪...\n");
rcvreq (g_sockfd);
return 0;
}
Linux局域网中 TCP 多线程 Server + Client 聊天室程序源码
最新推荐文章于 2022-03-18 10:56:23 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)