linux多线程聊天室,多线程的聊天室

#include int  sock; /* POSIX用int 来描述socket */

/* 多线程 TCP chat 服务器*/

#define MAX_USERS 30

/* 在线用户表,用下标表示对应的socket, online_user[8] =1 ,表示socket fd =8的socket 在线,=0表示下线*/

char online_user[MAX_USERS];

/* 用来保护在线用户表 online_user*/

pthread_mutex_t user_lock;

void exit_handler(int sig)

{

close(sock);

pthread_mutex_destroy(&user_lock);

exit(0);

}

void * thread_fn(void *arg)

{

char buffer[1024];

int len,fd;

int client_sock  = (int)arg;

while(1)

{

/* 接收客户端数据*/

len = recv(client_sock,buffer,sizeof(buffer)-1,0);

if(len <=0)

{/* 通常是客户端已经关闭,从在线用户表把当前sock 清掉*/

perror("recv");

pthread_mutex_lock(&user_lock);

online_user[client_sock] =0;

pthread_mutex_unlock(&user_lock);

break;

}

buffer[len] =0;

fprintf(stdout,"client:%s\n",buffer);

/* 把数据轮播到其它客户端*/

for(fd=0; fd< MAX_USERS ;fd++)

{

if((online_user[fd]  == 0) || (fd == client_sock))

continue;

len = send(fd,buffer,len,0);

if(len<= 0)

{

perror("send");

pthread_mutex_lock(&user_lock);

online_user[client_sock] =0;

pthread_mutex_unlock(&user_lock);

break;

}

}

}

close(client_sock);

}

int main(int argc,char * argv[])

{

unsigned short port = 9000;

socklen_t addrlen;

struct sockaddr_in local_addr,client_addr;

int client_sock,len,i;

pthread_t th;

const char * welcome_msg = "Welcom to Chat Server ,ver 1.0";

signal(SIGINT,exit_handler);

if(argc>1)

{

port = (unsigned short )atoi(argv[1]);

}

/* ------------第一步:创建socket ----------------*/

sock = socket(PF_INET,SOCK_STREAM,0); /* ipv4,TCP,任意协议 */

if(sock == -1)

{

perror("socket");

exit(-1);

}

fprintf(stdout,"TCP char Server ,listen on %d,pit %d\n",port,getpid());

/* ----------------第二步:绑定端口和网卡----------------------*/

/* struct socketaddr_in 来指明这个SOCKET绑定在本地的哪一个的端口和哪一块网卡*/

memset((void *)&local_addr,0,sizeof(local_addr));

local_addr.sin_family = AF_INET ; /* ip v4 */

local_addr.sin_port = htons(port); /* 端口号,要用网络序*/

/* 可以取值 INADDR_ANY 表示这个socket可以这一台机器所有网卡上进行通信*/

/* 如果本机一个某一个网卡的IP地址,表示只在这一块网卡进行通信*/

local_addr.sin_addr.s_addr = INADDR_ANY;  /* INADDR_ANY = 0x0 */

{

int val = 1;

setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof (val));

}

if(bind(sock,(struct sockaddr *)&local_addr,sizeof(local_addr)) == -1)

{

perror("bind");

close(sock);

exit(-2);

}

/* ----------第三步:通知内核的PS开始侦听客户端请求-------------*/

if(listen(sock,20) == -1)

{

perror("listen");

close(sock);

exit(-3);

}

/* 清空在线用户表,初始化锁*/

for(i=0 ; i < MAX_USERS ;i++)

online_user[i] =0;

if(pthread_mutex_init(&user_lock,NULL)!=0)

{

perror("mutex_init");

}

/*------ 第四步:接收客户端请求--------------------------*/

while(1)

{

addrlen = sizeof(client_addr);

client_sock = accept(sock,(struct sockaddr *)&client_addr,&addrlen);

if(client_sock == -1)

{

perror("accept");

continue;

}

if(client_sock > MAX_USERS)

{

char * close_msg = "online user too many";

fprintf(stdout,"new socket %d is too big,max user is %d\n",client_sock,MAX_USERS);

send(client_sock,close_msg,strlen(close_msg)+1,0);

close(client_sock);

continue;

}

/* 发送欢迎信息*/

send(client_sock,welcome_msg,strlen(welcome_msg)+1,0);

/* 把新联接的socket加入到在线用户表当中*/

pthread_mutex_lock(&user_lock);

online_user[client_sock] =1;

pthread_mutex_unlock(&user_lock);

fprintf(stdout,"client addr %s,port %d,sock %d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),client_sock);

pthread_create(&th,NULL,thread_fn,(void *)client_sock);

}

exit_handler(100);

}

客户端:代码比较简单

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目简介: 采用I/O复用技术select实现socket通信,采用多线程负责每个客户操作处理,完成Linux下的多客户聊天室! OS:Ubuntu 15.04 IDE:vim gcc make DB:Sqlite 3 Time:2015-12-09 ~ 2012-12-21 项目功能架构: 1. 采用client/server结构; 2. 给出客户操作主界面(注册、登录、帮助和退出)、登录后主界面(查看在线列表、私聊、群聊、查看聊天记录、退出); 3. 多客户可同时连接服务器进行自己操作; ##服务器端## 1. server.c:服务器端主程序代码文件; 2. config.h:服务器端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:服务器端公共函数的实现文件; 4. list.c:链表实现文件,用于维护在线用户链表的添加、更新、删除操作; 5. register.c:服务器端实现用户注册; 6. login.c:服务器端实现用户登录; 7. chat.c:服务器端实现用户的聊天互动操作; 8. Makefile:服务器端make文件,控制台执行make命令可直接生成可执行文件server ##客户端## 1. client.c:客户端主程序代码文件; 2. config.h:客户端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:客户端公共函数的实现文件; 4. register.c:客户端实现用户注册; 5. login.c:客户端实现用户登录; 6. chat.c:客户端实现用户的聊天互动操作; 7. Makefile:客户端make文件,控制台执行make命令可直接生成可执行文件client;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值