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

文件組成

編譯、服務器端運行

客戶端運行

其他客戶端進入聊天室也效仿上

下課!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM