**
计算机网络——linux下多线程聊天室
**
客户端 client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int sockfd;
//获取当前时间
int GetTime(char *nowT) {
time_t now;
struct tm *pTM;
time(&now);
pTM = localtime(&now);
sprintf(nowT, "%04d-%02d-%02d %02d:%02d:%02d\n ",
pTM->tm_year+1900, pTM->tm_mon+1, pTM->tm_mday,
pTM->tm_hour, pTM->tm_min, pTM->tm_sec);
return 0;
}
//接收服务器消息
void *TalkWithOther(void *arg)
{
char buf[240];
while(1)
{
bzero(buf,sizeof(buf));
recv(sockfd,buf,sizeof(buf),0);
printf("%s\n",buf);
}
}
int main(int argc,char **argv)
{
if(argc != 3)
{
perror("参数输入错误!");
return -1;
}
//建立socket对象
sockfd = socket(AF_INET,SOCK_STREAM,0);
//准备连接地址
struct sockaddr_in addr;
addr.sin_family = AF_INET; //使用网络套接字
addr.sin_addr.s_addr = inet_addr(argv[1]); //输入服务器地址
addr.sin_port = htons(atoi(argv[2])); //输入服务器端口
int addr_len = sizeof(addr);
//连接服务器
int ret = connect(sockfd,(struct sockaddr*)&addr,addr_len);
if(ret == -1)
{
perror("connect error\n");
return -1;
}
char buf[200] = {}; //聊天内容
char buf_send[240] = {}; //加上当前时间的聊天内容
char name[20] = {}; //昵称
char *nowTime;
//发送名字
printf("请输入您的昵称:");
scanf("%s",name);
getchar();
send(sockfd,name,strlen(name),0);
//printf("%s已进入聊天室\n",name);
//创建接收消息的线程
pthread_t tid;
pthread_create(&tid,NULL,TalkWithOther,NULL);
//循环获取键盘输入并发送
while(1)
{
fgets(buf,sizeof(buf),stdin); //输入聊天内容
buf[strlen(buf)-1]='\0'; //去除fgets读取到的最后的换行符
//若输入quit,退出聊天室
if(strcmp("quit",buf)==0)
{
send(sockfd,buf,strlen(buf),0);
printf("%s,您已退出聊天室\n",name);
return 0;
}
else{
GetTime(nowTime); //获取当前时间
printf("%s\t%s%s\n",name,nowTime,buf); //将消息在本地显示出来
bzero(buf_send,sizeof(buf_send)); //清空发送字符串
strcat(buf_send,nowTime); //将当前时间写入字符串
strcat(buf_send,buf); //将聊天内容写入发送字符串
send(sockfd,buf_send,strlen(buf_send),0);
}
}
return 0;
}
服务器server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#define MAX 50 //定义最大连接人数
//存储客户端地址的结构体数组
struct sockaddr_in client_addr[50];
int client_len = sizeof(client_addr[0]);
//连接后记录confd数组
int confd[MAX] = {};
//连接人数
int count = 0;
void* Talk(void *indexp)
{
int index = *(int *)indexp;
int i;
char buf_recv[200] = {};
char buf_send[200] = {};
//读取用户姓名
char name[20] = {};
recv(confd[index],name,sizeof(name),0);
sprintf(buf_send,"%s已加入聊天室\n",name,buf_recv);
for(i=0;i<=count;++i)
{
if(confd[i]==0)
continue;
send(confd[i],buf_send,sizeof(buf_send),0);
}
while(1)
{
bzero(buf_recv,sizeof(buf_recv));//清空缓存字符串
recv(confd[index],buf_recv,sizeof(buf_recv),0);//读取接收字符串
//判断是否退出
if(strcmp("quit",buf_recv)==0)
{
sprintf(buf_send,"%s已退出聊天室\n",name);
//对除退出用户以外所有用户广播退出消息
for(i=0;i<=count;++i)
{
if(i==index||confd[i]==0)
continue;
send(confd[i],buf_send,strlen(buf_send),0);
}
confd[index] = 0;
pthread_exit(0);//结束线程
}
//将接收到的字符串复制进发送字符串中
sprintf(buf_send,"%s\t%s",name,buf_recv);
for(i=0;i<=count;++i)
{
if(i==index||confd[i]==0)
continue;
send(confd[i],buf_send,sizeof(buf_send),0);
}
}
}
int main(int argc,char **argv)
{
printf("聊天室服务器端开始运行\n");
//创建套接字
int server_sockfd = socket(AF_INET,SOCK_STREAM,0);
//准备地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;//指定网络套接字
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//接受所有IP地址的连接
server_addr.sin_port = htons(3898);//绑定到3898端口
int server_len = sizeof(server_addr);
//绑定套接字
bind(server_sockfd, (struct sockaddr*)&server_addr, server_len);
//设置最大排队数
listen(server_sockfd,MAX);
int index;//下标
while(count < MAX)
{
confd[count] = accept(server_sockfd,(struct sockaddr*)&client_addr[count],&client_len);
++count;
index=count-1;
//创建新线程
pthread_t tid;
pthread_create(&tid,NULL,Talk,&index);
}
return 0;
}