这是本人在学习Unix C是的练习
//server.cpp
//TCP聊天室服务器
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct client{
char name[20];//客户端连接上来时 输入的姓名
int fds;//客户端的socket
};
struct client c[100]={0};//最多记录100个sockfd,最多允许100个用户进入
int sockfd;//服务器的sockfd
int size = 0;//记录客户端的个数,数组的索引
int online = 0;
char filename[4096] = {0};
char* IP = "192.168.66.42";//获取本机IP
short PORT = 20000;
typedef struct sockaddr SA;//用作通信地址类型转换的时候使用
//初始化服务器的网络,创建socket..
void init(){
system("clear");
printf("聊天室服务器开始启动..\n");
//创建socket
sockfd = socket(PF_INET,SOCK_STREAM,0);
if(sockfd == -1){
perror("创建socket失败");
printf("服务器启动失败\n");
exit(-1);
}
//准备通信地址
struct sockaddr_in addr;//网络通信的地址信息
addr.sin_family = PF_INET;//协议簇
addr.sin_port = htons(PORT);//端口
addr.sin_addr.s_addr = inet_addr(IP);//IP地址结构体
int reuseaddr = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr));
//绑定socket和通信地址
if(bind(sockfd,(SA*)&addr,sizeof(addr))==-1){
perror("绑定失败");
printf("服务器启动失败\n");
exit(-1);
}
printf("成功绑定\n");
//设置监听
if(listen(sockfd,100)==-1){
perror("设置监听失败");
printf("服务器启动失败\n");
exit(-1);
}
printf("初始化服务器成功\n");
//等待客户端连接和通信部分写到另一个函数中
}
//用来分发消息的函数
void sendMsgToAll(char * msg){
int i=0;
for(;i0){//接受到名字
strcpy(c[size].name,name);
}
m_id = size;
size++;
//进入线程之后,先群发一条提示,提示某某客户端连接上来
char tishi[100]={};
sprintf(tishi,"%s 上线\n",c[size-1].name);
online += 1;
sendMsgToAll(tishi);
int fd = *(int*)p;
printf("Name:%s 上线\n",c[size-1].name);
//通信,接受消息,分发消息
while(1){
char buf[100]={};
recv(fd,buf,sizeof(buf),0);
if(strncmp(buf,"bye",3) == 0/*recv(fd,buf,sizeof(buf),0)<=0*/){//接受信息
// printf("fd=%dquit\n",fd);//recv函数返回小于0,则
//表示有客户端断开,打印quit
//之后将退出的客户端的socket描述符重新置成0
int i;
for(i=0;i
//client.cpp
//聊天室客户端
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sig_close();
int sockfd;//客户端socket
char *IP="192.168.66.42";//本地IP
short PORT=20000;//服务器服务端口
typedef struct sockaddr SA;
char name[30];//用于存放聊天人的昵称
//客户端也分为几步:
//启动客户端,连接服务器
void init(){
printf("聊天室客户端开始启动\n");
sockfd=socket(PF_INET,SOCK_STREAM,0);
struct sockaddr_in addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
if(connect(sockfd,(SA*)&addr,sizeof(addr))==-1){
perror("无法连接到服务器");
printf("客户端启动失败\n");
exit(-1);
}
printf("客户端启动成功\n");
}
//开始通信
void start(){
//发送消息之前
//启动一个线程,用来接受服务器发过来的消息
pthread_t pid;
void* recv_thread(void*);//线程函数的声明
pthread_create(&pid,0,recv_thread,0);
char buf[100] = {0};
while(1){//内部不断的发送数据
bzero(buf,100);
fgets(buf,sizeof(buf),stdin);
if(strncmp(buf,"clear",5) == 0){
system("clear");
}
else if(strncmp(buf,"bye",3) == 0){
sig_close();
}
else{
send(sockfd,buf,sizeof(buf),0);//发送消息给服务器
}
}
}
void * recv_thread(void* p){
while(1){
char buf[100]={};//存储读到的消息
if(recv(sockfd,buf,sizeof(buf),0)<=0){//接收出错
return ;//结束线程
}
if(strncmp(buf,"close",5) == 0){
printf("服务器已关闭,现在退出客户端\n");
close(sockfd);
exit(0);
}
else{
printf("%s",buf);
}
}
}
void sig_close(){
//关闭客户端的socket
char buf[] = "bye";
send(sockfd,buf,sizeof(buf),0);
close(sockfd);
exit(0);
}
int main(){
//f发信号,关闭socket
signal(SIGINT,sig_close);//自定义信号处理函数,做好善后工作
printf("请输入您的名字:");
scanf("%s",name);
scanf("%*[^\n]");
scanf("%*c");
init();//启动客户端,连接服务器
send(sockfd,name,sizeof(name),0);//把名字给服务器
start();//通信
}
时间比较紧,所以功能不太完善