Linux 系统下的简单聊天室(C语言实现)
server端
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<pthread.h>
#define MAXLINE 100
#define LISTENQ 20
#define PORT 5000
#define MAXFD 20
void *get_client(void *);
FILE *fp;
int i,maxi=-1;//maxi表示当前client数组中最大的用户的i值
int client[MAXFD];
int main(void)
{
int connfd,listenfd,sockfd; //connfd存放accept函数的返回值,listenfd表示监听的套接口,
//sockfd用于遍历client的数组
socklen_t length;
fp=fopen("student.txt","w");
struct sockaddr_in server;
struct sockaddr tcpaddr;
pthread_t tid;
listenfd=socket(AF_INET,SOCK_STREAM,0); //建立套接口并监听
if(listenfd<0){
printf("创建socket失败\n");
exit(1);
}
memset(&server,0,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr=htonl(INADDR_ANY);
if( bind(listenfd,(struct sockaddr*)&server,sizeof(server))<0 )
{
printf("绑定套接口失败\n");
exit(1);
}
length=sizeof(server);
if(getsockname(listenfd,(struct sockaddr*)&server,&length)<0)
{
printf("取服务器的端口号失败\n"); //取得服务器的端口号
exit(1);
}
for(i=0;i<MAXFD;i++)
client[i]=-1; //initialize the client column
listen(listenfd, LISTENQ);
printf("服务器监听端口 %d...\n", ntohs(server.sin_port));
printf("欢迎来到本聊天室\n");
for(;;)
{
connfd=accept(listenfd, &tcpaddr, &length);
for(i=0;i<MAXFD;i++)
if(client[i]<0)
{
client[i]=connfd;
break;
} //用户链接成功后,在client数组中保存用户套接口号
if(i==MAXFD-1)
{
printf("对不起,聊天室已经满了!\n"); //若此时以达到用户最大值,则退出链接
exit(0);
}
if(i>maxi) maxi=i;
pthread_create(&tid,NULL,&get_client,(void *)(intptr_t)connfd); //若链接成功,为此用户创建一个新线程
} //运行get_client函数,处理用户请求
}
void *get_client(void *sockfd) //get_client函数
{
char buf[MAXLINE];
int rev;
if (((intptr_t)sockfd)<0)
printf("\n新用户进入聊天室失败\n");
else
{
printf("\n新用户进入聊天室...\n");
do
{
memset(buf,0,sizeof(buf)); //初始化buffer
if ((rev = recv((intptr_t)sockfd,buf,1024,0))<0)
printf("\n读取用户消息失败\n");
if (rev==0)
printf("\n用户终止链接\n");
else
{
printf("%s\n", buf); //若无异常,输出此用户消息
for(i=0;i<=maxi;i++)
send(client[i],buf,strlen(buf)+1,0);//将刚收到的用户消息分发给其他各用户
fputs(buf,fp);
}
}while (rev != 0);
fclose(fp);
}
close((intptr_t)sockfd);
return(NULL);
}
client端
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<unistd.h>
#include<pthread.h>
#define TRUE 1
#define PORT 5000
int quit=0;
void *get_server(void *);
int main(void)
{
int connfd,snd,slenth;
struct sockaddr_in server;
struct hostent *hp;
char honame[20],msg2[1024],msg1[1024],cln[102],qstr[]={"Quit"}; //
pthread_t tid;
printf("请输入服务器IP地址\n");
scanf("%s*",honame);
printf("创建套接口中\n");
if((connfd= socket(AF_INET, SOCK_STREAM, 0))<0)
printf("建立套接口失败\n");
if ((hp= gethostbyname(honame))== NULL) /
{
printf("获取服务器IP地址失败\n");
exit(1);
}
else printf("套接口建立成功,链接服务器中...\n");
memcpy(&server.sin_addr,hp->h_addr,hp->h_length);
server.sin_family = AF_INET;
server.sin_port=htons(PORT);
if(connect(connfd,(struct sockaddr*)&server,sizeof(server))<0)
{
printf("链接服务器失败\n");
exit(1);
}
printf("链接服务器成功\n");
printf("欢迎来到聊天室\n");
//聊天室
printf("请输入你的用户昵称\n");
scanf("%s",msg1);
slenth=strlen(msg1);
msg1[slenth]=':';
msg1[slenth+1]='\0';
strcpy(cln,msg1); //保存用户昵称在名为cln的数组中
pthread_create(&tid,NULL,&get_server,(void *)(intptr_t)connfd);//为客户端创建一个线程用于监听,调用get_server函数
printf("\n开始聊天吧 (\"Quit\"断开链接)\n");
while(TRUE)
{
printf("\n");
fgets(msg2,100,stdin);
//scanf("%[^\n]",msg2);
if(strcmp(msg2,qstr)==0)
{
close(connfd);
quit=1; //若用户输入"Quit"字符则关闭发送套接口,并将quit置为1
}
else
{
strcat(msg1,msg2);//将消息前加上用户昵称
snd=send(connfd,msg1,strlen(msg1)+1,0);//否则发送消息给服务器
strcpy(msg1,cln);
if(snd<0)
printf("\n发送错误\n");
}
}
}
void *get_server(void* sockfd) //get_server函数,用于接受服务器转发的消息
{
char buf[1024];
int rev;
if(((intptr_t)sockfd)<0)
printf("\n接受服务器消息失败\n");
else
{
printf("\n\007\n");
for(;;)
{
if(!quit)//只要quit不为1,则一直接受服务器消息
{
if ((rev = recv((intptr_t)sockfd,buf,1024,0))>0)
printf("\n\007%s\n", buf);
if (rev==0)
{
printf("\n服务器终止链接\n");
quit=1;
continue;
}
printf("\n");
}
else
{
close((intptr_t)sockfd);//关闭此套接口
break;
}
}
return(NULL);
}
}
Makefile
target : server.o client.o
gcc -o server server.o
gcc -o client client.o
server.o : server.c
gcc -c -o server.o server.c
client.o : client.c
gcc -c -o client.o client.c
clean :
rm *.o server client
.PHONY : clean
文件组成
编译、服务器端运行
客户端运行
其他客户端进入聊天室也效仿上