聊天服务器

/*一款简单的聊天服务器:支持群聊,显示用户在线的人数以及提醒新用户在线*/



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


//带头节点的双向循环链表
typedef struct _node{
int sockfd;
char *buf;
struct _node *prev,*next;
}Node;


Node *head;//链表充当容器!
void init(){
head = malloc(sizeof(Node));
head->sockfd = 0;
head->prev = head;
head->next = head;
}


void insert_back(int sockfd,char *ch){
//创建并初始化一个新节点
Node* p = malloc(sizeof(Node));
p->sockfd = sockfd;
p->buf = ch;
p->prev = head->prev;
p->next = head;
head->prev->next = p;
head->prev = p;
}


void travel(){
Node* p = head->next;
while(p!=head){
printf("%d\n",p->sockfd);
printf("%s\n",p->buf);
p = p->next;
}
}


int size(){
int cnt = 0;
Node* p = head->next;
while(p!=head){
++cnt;
p = p->next;
}
return cnt;
}


void erase(int sockfd){
Node* p = head->next;
while (p != head) {
if(p->sockfd == sockfd){
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
return;
}
p = p->next;
}
}


void send_all(char* msg) {
Node* p = head->next;
while (p != head) {
write(p->sockfd, msg, strlen(msg));
p = p->next;
}
}
//wp\r\n   256
int read_line(int cfd, char* buf, int size) {
int i;
for (i = 0; i < size - 1; ++i) {
int n = read(cfd, buf + i, 1);
if (1 == n) {
if (buf[i] == '\n') {
++i;
break;
}
} else {
perror("read_line");
return -1;
}
}
buf[i] = '\0';
return i;
}
void process(int *pcfd){
int cfd = *pcfd;
printf("cfd:%d\n",cfd);
//发送欢迎信息
char wel_msg[256] = "welcome to xjj's chat server!\r\n";
write(cfd,wel_msg,strlen(wel_msg));
//写入用户名
char name_msg[64] = "please input your name:\r\n";
write(cfd,name_msg,sizeof(name_msg));
char name_buf[64] = { '\0' };
read_line(cfd, name_buf, sizeof(name_buf));
char *p = strchr(name_buf, '\r');
*p = '\0';
//将上线的用户保存在在线列表中
insert_back(cfd,name_buf);
//服务器的日志
char online_msg[256] = {'\0'};
sprintf(online_msg,"a new user [%s] is online!current user num:[%d]!\n",name_buf,size());
send_all(online_msg);
printf(online_msg);
//群发(转发)
while(1){
char buf[256] = {'\0'};
int n = read_line(cfd,buf,sizeof(buf));
printf("read %d,%s\n",n,buf);
if (n < 0 || strncasecmp(buf, "quit", 4) == 0)break;
time_t now = time(NULL);
struct tm* tm = localtime(&now);
char tbuf[64] = {'\0'};
strftime(tbuf,sizeof(tbuf),"[ %H:%M:%S ]",tm);
char msg[512] = {'\0'};
sprintf(msg,"%s:%s%s",name_buf,tbuf,buf);
send_all(msg);
}
//将下线的用户从在线列表中清除
erase(cfd);
//发送欢送信息
char welback_msg[256] = "welcome back to xjj's chat server!\r\n";
write(cfd, welback_msg, strlen(welback_msg));
//发送新用户下线的信息
char offline_msg[256] = {'\0'};
sprintf(offline_msg,"a user [ %s ] is offline!,current user num:[%d]!\n",name_buf,size());
send_all(offline_msg);
printf(offline_msg);
close(cfd);//exit(0)退出了整个进程 此程序有一个进程两个线程!
}


int start(port){
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket:");
return -1;
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


struct sockaddr_in ser_addr;
ser_addr.sin_family = PF_INET;
ser_addr.sin_addr.s_addr = INADDR_ANY;
ser_addr.sin_port = htons(port);


int ret = bind(sockfd, (struct sockaddr*) &ser_addr, 16);
if (ret < 0) {
perror("bind:");
return -1;
}


ret = listen(sockfd, 20);
if (ret < 0) {
perror("listen:");
return -1;
}
printf("xjj's chat server is ready!\n");


while (1) {
int cfd = accept(sockfd, NULL, NULL);
if (cfd < 0) {
perror("accept:");
continue;
}
pthread_t tid;
pthread_create(&tid,NULL,(void*)process,&cfd);
}
close(sockfd);
return 0;
}


int main(){
init();//初始化链表容器(放客户端)!
start(2000);//起动聊天服务器!
return 0;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值