#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<time.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>
#define MaxNum 8 //最大连接数量
#define bufSize 0x100 //消息缓冲区
int re_ret,rwflag = 1;
FILE *rfp,*wfp;//读写指针
pthread_mutex_t mutex;//定义一个锁
//通讯线程函数
void* ClientThread(void*);
//获取系统时间,结果通过传入的指针返回
void GetTime(char*);
//写入日至
void WriteToNote(char*);
//发送日志到客户端
void ReadNoteSend(int);
typedef struct tem //设备传感器
{
int sock;//连接标识符
char buf[bufSize];//收发消息缓冲区
}TEM;
TEM tem[MaxNum];//定义MaxNum个用户
//搭建tcp服务器
int main()
{
for(int i=0;i<MaxNum;i++)//初始化设备状态
{
tem[i].sock = 0;
memset(tem[i].buf,0,bufSize);
}
int ret,_thread;
int sockfd;
int connfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建通信套接字(TCP)
if(sockfd==-1){
printf("socket failed\n");
exit(-1);
}
//定义addr存入本机地址信息
struct sockaddr_in addr;
addr.sin_family=AF_INET;//协议
addr.sin_port=htons(7788);//端口
addr.sin_addr.s_addr=inet_addr("0");//0代表本机
ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));//绑定地址信息(sockfd + addr)
if(ret==-1){
printf("bind faild\n");
exit(-1);
}
listen(sockfd, 8);//进入监听状态,建立一个监听队列
wfp = fopen( "note.txt", "r" );//判断日志是否存在,存在就追加
if(wfp == NULL)
{
wfp = fopen( "note.txt", "w" );//日志不存在,就创建
if(wfp == NULL)
{
perror("open file error:");//只有上面的函数设置了error全局错误号,才可使用,会根据error输出对应的错误信息
exit(-1);
}
}
fclose(wfp);
printf("sever open success,waiting...\n");
pthread_mutex_init(&mutex, NULL);//初始化锁
while(1){
connfd = accept(sockfd, NULL, NULL);//检测到接入请求
pthread_t tid;
//创建一个线程去处理
_thread = pthread_create(&tid, NULL, ClientThread, (void *)&connfd);
if (!tid) {
printf("CreateThread失败:\n");
//break;
}
//处理完后回收
pthread_detach(tid);
}
close(connfd);
close(sockfd);
}
//通讯线程函数
void* ClientThread(void* argc)
{
int IONum;//线程对应设备的标识号
char buffer[bufSize],buf[bufSize];//临时接收消息缓存
int ret = recv(*(int *)argc, buffer, sizeof(buffer),0);//接收标识消息
if(ret <= 0)//连接判断
{
printf("device(%d) quit\n",*(int *)argc);
pthread_exit(NULL) ;
}
buffer[ret] = 0;
if(*buffer == 2)//监控设备
{
for(IONum=0; IONum<MaxNum-2; IONum++)//分配设备通信空间
{
if(!tem[IONum].sock)
{
strcpy(tem[IONum].buf,buffer);//写入数据,确保客户端请求时有数据
tem[IONum].sock = *(int *)argc;//保存连接标识号
printf("connect a device(%d)\n",tem[IONum].sock);
memset(buf,0,sizeof(buf));
sprintf(buf,"connect a device(%d)\n",tem[IONum].sock);//构造日志消息
memset(buffer,0,sizeof(buffer));
GetTime(buffer);//获取时间
strcat(buffer,buf);
pthread_mutex_lock(&mutex);//上锁
WriteToNote(buffer);
pthread_mutex_unlock(&mutex);//解锁
break;
}
}
if(IONum >= MaxNum-2)//限制连接上限
{
strcpy(buffer, "\3device over,can't connect more\0");
printf("device over,exit connect(%d)\n",*(int *)argc);
send(*(int *)argc,buffer,strlen(buffer),0);//返回连接上限
pthread_exit(NULL);//结束线程
}
}
else if(*buffer == 1)//客户端
{
if(!tem[MaxNum-2].sock)//限制仅一个客户端连接
{
tem[MaxNum-2].sock = *(int *)argc;//保存连接标识号
IONum = MaxNum-2;
printf("connect a client(%d)\n",tem[IONum].sock);
memset(buf,0,sizeof(buf));
sprintf(buf,"connect a client(%d)\n",tem[IONum].sock);//构造日志消息
memset(buffer,0,sizeof(buffer));
GetTime(buffer);//获取时间
strcat(buffer,buf);
pthread_mutex_lock(&mutex);//上锁
WriteToNote(buffer);
pthread_mutex_unlock(&mutex);//解锁
}
else
{
strcpy(buffer, "\3other client had connect~\0");
printf("client over,exit connect(%d)\n",*(int *)argc);
send(*(int *)argc,buffer,strlen(buffer),0);//返回连接客户端
pthread_exit(NULL);//结束线程
}
}
else if(*buffer == 4)//客户端日志
{
if(!tem[MaxNum-1].sock)//限制仅一个连接
{
tem[MaxNum-1].sock = *(int *)argc;//保存连接标识号
IONum = MaxNum-1;
printf("client request the note\n");
}
else
{
strcpy(buffer, "\3request failed\0");
printf("client over,exit connect(%d)\n",*(int *)argc);
send(*(int *)argc,buffer,strlen(buffer),0);//返回连接客户端
pthread_exit(NULL);//结束线程
}
}
else//非法请求
{
printf("connect(%d) violations,exit\n",*(int *)argc);
pthread_exit(NULL);
}
strcpy(buffer, "OK,keep going on\0");
send(tem[IONum].sock,buffer,strlen(buffer),0);//发送保活消息
while(1)
{
int ret = recv(tem[IONum].sock, tem[IONum].buf, sizeof(buffer),0);//接收消息
if(ret <= 0)//连接判断
{
if(IONum<MaxNum-2)
printf("device(%d)) quit\n", tem[IONum].sock);//监测器断连
else if(IONum == MaxNum-2)
printf("client(%d)) quit\n", tem[IONum].sock);//客户端断开
else
printf("client(%d)) request over\n", tem[MaxNum-2].sock);//关闭日志
tem[IONum].sock = 0;//空间 置0,后来者可连接
break;
}
tem[IONum].buf[ret] = 0;
if(*tem[IONum].buf == 2)//回显&&日志
{
float T = tem[IONum].buf[1] + tem[IONum].buf[2]*0.1;
printf("device%d temperature: %.1f°C\t%d\n",IONum+1,T,(int)T/20+1);
memset(buf,0,sizeof(buf));
sprintf(buf,"device%d temperature: %.1f°C\t%d\n",IONum+1,T,(int)T/20+1);//构造日志消息
memset(buffer,0,sizeof(buffer));
GetTime(buffer);//获取时间
strcat(buffer,buf);
pthread_mutex_lock(&mutex);//上锁
WriteToNote(buffer);
pthread_mutex_unlock(&mutex);//解锁
}
else if(*tem[IONum].buf == 1)//客户端请求,回应
{
memset(buffer,0,sizeof(buffer));//清空缓存
buffer[0] = 1;
for(int i=0;i<MaxNum-2;i++)
{
if(tem[i].sock)//有连接,就有数据
{
float t = tem[i].buf[1] + tem[i].buf[2]*0.1;
char buf[0x20];
memset(buf,0,0x20);
sprintf(buf,"%d+%.1f°C+%c;",i+1, t, (int)(t/20)+1);//格式化消息:id+temperature+等级
strcat(buffer,buf);
}
}
if(strlen(buffer) == 1)//暂无设备
{
char buff[0x20];
memset(buff,0,0x20);
sprintf(buff,"%d+N/A+%c;",1,6);//无设备连接
strcat(buffer,buff);
}
send(tem[IONum].sock, buffer,strlen(buffer),0);
}
else if(*tem[IONum].buf == 4)//客户端请求查看日志
{
pthread_mutex_lock(&mutex);//锁
system("cp note.txt note1.txt");//复制一个副本
pthread_mutex_unlock(&mutex);//解锁
ReadNoteSend(tem[IONum].sock);//发送副本
}
}
pthread_exit(NULL);
}
void GetTime(char* timeStr)//获取时间
{
char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
time_t timep;
struct tm *p;
time(&timep);
p=localtime(&timep); /*取得当地时间*/
sprintf(timeStr,"%d/%d/%d %s %02d:%02d:%02d : ", (1900+p->tm_year),(1+p->tm_mon), p->tm_mday, wday[p->tm_wday],p->tm_hour, p->tm_min, p->tm_sec);//格式化字符串
return;
}
void WriteToNote(char* buffer)//写日志
{
wfp = fopen( "note.txt", "a+" );
int rwt = fwrite(buffer, strlen(buffer), 1, wfp);
fclose(wfp);
return;
}
void ReadNoteSend(int sock)
{
char buf[0x1000];
rwflag = 0;
rfp = fopen( "note1.txt", "r" );//读取日志文件发送
while(!feof(rfp))
{
memset(buf,0,0x1000);
int ret = fread(buf,sizeof(buf),1,rfp);
send(sock,buf,(strlen(buf)<sizeof(buf)?strlen(buf):sizeof(buf)),0);
}
}
Asteri5m
- 粉丝: 2
- 资源: 3