linux 下用c语言编写的聊天室程序服务器和客户端Word格式文档下载.docx
《linux 下用c语言编写的聊天室程序服务器和客户端Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《linux 下用c语言编写的聊天室程序服务器和客户端Word格式文档下载.docx(19页珍藏版)》请在冰豆网上搜索。
c_client_c*temp_c1=NULL,*temp_c2=NULL;
//等待的
//初始化client信息
voidinit_client(){
inti=0;
for(i=0;
i<
MAX_CLIENT;
i++){
client[i].sockfd=-1;
memset(client[i].name,0,20);
client[i].pid=-1;
client[i].flg=-1;
}
}
//查找结构体数组中sockfd为-1的下标值
intfind_fd(c_client*client){
while(i<
MAX_NUM){
//printf("
====%d\n"
client[i].sockfd);
if(client[i].sockfd==-1)
returni;
i++;
return-1;
//判断登录格式
intlogform(char*buf){
char*p=strstr(buf,"
LOGIN\r\n"
);
intn=strlen(buf);
char*q=p+n-4;
if(p!
=NULL&
&
p+7!
=q&
strcmp(q,"
\r\n\r\n"
)==0)
return1;
else
return0;
intcmpname(char*buf,c_client*p_client){
char*p=strtok(buf+7,"
while(client[i].sockfd!
=-1&
client[i].sockfd!
=p_client->
sockfd&
i
<
if(strcmp(client[i].name,p)==0)
return0;
return1;
//SHOW
voidshowuser(c_client*p_client){
charbuf[1024]={0};
strcpy(buf,"
200\r\n"
MAX_NUM;
if(client[i].sockfd!
=-1){
sprintf(buf+strlen(buf),"
%s\r\n"
client[i].name);
}
sprintf(buf+strlen(buf),"
\r\n"
send(p_client->
sockfd,buf,strlen(buf),0);
//ALL
voidsendto_all(c_client*p_client,char*buf){
charsendbuf[1024]={0};
sprintf(sendbuf,"
AFROM\r\n%s\r\n%s"
p_client->
name,buf+5);
client[i].flg!
=-1)
if(send(client[i].sockfd,sendbuf,strlen(sendbuf),0)<
=0){
printf("
senderrrrrr\n"
exit
(1);
}
intfindname(char*name){
strcmp(client[i].name,name)==0)
returnclient[i].sockfd;
return0;
//TO
voidsendto_one(c_client*p_client,char*buf){
charname[20]={0};
char*p=strtok(buf+4,"
//TO\r\n:
4个字符后取出\r\n前的名字
strcpy(name,p);
intsock=findname(name);
if(!
sock){
sprintf(sendbuf,"
ERROR2\r\n%s用户不存在\r\n\r\n"
name);
send(p_client->
sockfd,sendbuf,strlen(sendbuf),0);
}else{
FROM\r\n%s\r\n%s"
name,buf+4+strlen(
name)+2);
if(send(sock,sendbuf,strlen(sendbuf),0)<
=0){
printf("
exit
(1);
voidpthread_fun(void*cclient);
//quit
voidquit(c_client*p_client){
inti=0;
intidx;
charbuf[1024]={0};
c_client_c*temp;
printf("
--%s退出聊天室\n"
p_client->
name);
close(p_client->
sockfd);
p_client->
sockfd=-1;
pid=-1;
flg=-1;
sprintf(buf,"
NOTICE1\r\n%s退出聊天室\r\n\r\n"
memset(p_client->
name,0,20);
for(i=0;
i<
MAX_NUM;
i++){
if(client[i].sockfd!
send(client[i].sockfd,buf,strlen(buf),0);
if(head!
head->
next!
=NULL){
memset(buf,0,1024);
pthread_rwlock_rdlock(&
idx_lock);
idx=find_fd(client);
pthread_rwlock_unlock(&
client[idx].sockfd=head->
next->
sockfd;
pthread_rwlock_wrlock(&
wait_lock);
temp=head->
next;
head->
next=head->
free(temp);
sprintf(buf,"
NOTICE\r\n您已被唤醒,请继续操作\r\n\r\n"
send(client[idx].sockfd,buf,strlen(buf),0);
if(pthread_create(&
client[idx].pid,NULL,(void*)pthread_fun,(void*)&
client[idx])!
=0){
perror("
pthread_create"
pthread_detach(client[idx].pid);
voidpthread_fun(void*cclient){
c_client*p_client=(c_client*)cclient;
charbuf[MAX_SIZE]={0};
inti,n;
char*p;
%s"
"
NOTICE\r\n通讯通道开启\r\n\r\n"
if(send(p_client->
sockfd,sendbuf,strlen(sendbuf),0)<
printf("
senderr\n"
memset(sendbuf,0,1024);
while
(1){
memset(buf,0,MAX_SIZE);
n=recv(p_client->
sockfd,buf,sizeof(buf)-1,MSG_NOSIGNAL);
if(n<
close(p_client->
p_client->
break;
if(logform(buf)){
if(cmpname(buf,p_client)==0){
send(p_client->
sockfd,"
ERROR\r\n用户名重复\r\n\r\n"
26,0);
continue;
}else{
p_client->
flg=1;
p=strtok(buf+7,"
strcpy(p_client->
name,p);
sprintf(sendbuf,"
100\r\n%s\r\n\r\n"
sockfd,sendbuf,sizeof(sendbuf),0);
%s进入聊天室\n"
for(i=0;
if(client[i].sockfd!
client[i].sockfd
!
send(client[i].sockfd,sendbuf,sizeof(sendbuf),0);
}
memset(sendbuf,0,1024);
while
(1){
memset(buf,0,MAX_SIZE);
if((n=recv(p_client->
sockfd,buf,MAX_SIZE,0))<
perror("
recverr"
break;
}
//printf("
recv=%s\n"
buf);
if((p=strstr(buf,"
))!
*(p+4)
=='
\0'
){
if(!
strncmp(buf,"
SHOW\r\n\r\n"
8)){
showuser(p_client);
//客户端执行show后,发送给客户端已连接的用户
continue;
}
ALL\r\n"
5)){
sendto_all(p_client,buf);
TO\r\n"
4)){
sendto_one(p_client,buf);
QUIT\r\n\r\n"
8))
quit(p_client);
//break;
pthread_exit(NULL);
}else{
send(p_client->
ERROR\r\n信息不符合协议要求\r\n\r\n"
38,0);
}else{
send(p_client->
ERROR\r\n未登录,请您登录再进行其他操作\r\n\r\n"
56,0);
pthread_exit(NULL);
intmain(){
intser_sockfd,clt_sockfd;
structsockaddr_inaddr;
//pthread_rwlock_tidx_lock,wait_lock;
pthread_rwlock_init(&
idx_lock,NULL);
wait_lock,NULL);
init_client();
//创建服务器sockfd
if((ser_sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("
socket"
exit
(1);
//设置服务器网络地址
bzero(&
addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
//设置端口可重用
intopt=1;
setsockopt(ser_sockfd,SOL_SOCKET,SO_REUSEADDR,&
opt,sizeof(opt));
//将套接字绑定到服务器的网络地址上
if(bind(ser_sockfd,(structsockaddr*)&
addr,sizeof(addr))==-1){
bind"
bindsuccess\n"
//监听连接请求--监听队列长度为10
if(listen(ser_sockfd,10)==-1){
listen"
listensuccess\n"
if((clt_sockfd=accept(ser_sockfd,NULL,NULL))==-1){
accept"
idx=%d\n"
idx);
if(idx!
=-1){//连接末满
client[idx].sockfd=clt_sockfd;
if(pthread_create(&
client[idx].pid,NULL,(void*)pthread_fun,
(void*)&
perror("
pthread_detach(client[idx].pid);
}else{//连接已满,等待
temp_c1=(c_client_c*)malloc(sizeof(c_client_c));
temp_c1->
sockfd=clt_sockfd;
next=NULL;
pthread_rwlock_wrlock(&
if(head==NULL){
head=(c_client_c*)malloc(sizeof(c_client_c));
head->
next=temp_c1;
for(temp_c2=head;
temp_c2->
=NULL;
temp_c2=temp_c2->
next);
temp_c2->
pthread_rwlock_unlock(&
memset(buf,0,1024);
sprintf(buf,"
NOTICE\r\n服务器已满,请等候\r\n\r\n"
//客户端接受则等待
if(send(temp_c1->
sockfd,buf,strlen(buf),0)<
sendrerr\n"
*client.c
2012-6-18
arpa/inet.h>
termios.h>
staticintFLAGE=-1;
charname[20]={0};
voidfun_show(intsockfd){
charsendbuf[256]={0};
sprintf(sendbuf,"
if(send(sockfd,sendbuf,strlen(sendbuf),0)<
close(sockfd);
voidfun_all(intsockfd){
charsendbuf[MAX_SIZE]={0};
5);
输入发送的内容:
\n"
scanf("
sendbuf+5);
sprintf(sendbuf+strlen(sendbuf),"
if(send(sockfd,sendbuf,strlen(sendbuf),0)<
voidfun_one(intsockfd){
charname3[20]={0};
输入聊天对象:
"
name3);
TO\r\n%s\r\n"
输入聊天内容:
sendbuf+strlen(sendbuf));
voidfun_quit(intsockfd){
charsendbuf[256]="
;
close(sockfd);
void*pthread_fun(int*sock){
intsockfd