主控进程中开启的网络线程用于监听客户端的连接请求、连接成功后通过网络协议同客户端通信,比如查询客户端设备的在线状态、控制其开关状态等。
net_pro.h
#ifndef __SL2000_NET_H_
#define __SL2000_NET_H_
#define DEF_PORT 6899
int socket_init(int port);
void * client_pro(void * arg);
void * net_pro(void * arg);
int send_cmd(char cmd,char cmd_da,int sockfd);
int get_cmd(char * buf,char *cmd,int len);
#endif
net_pro.c
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include "config.h"
#include "net_pro.h"
int net_user;
unsigned char net_cmd;
unsigned char net_flag;
extern struct sys_all g_dev[1];
extern struct dev_fd g_dev_fd;
int socket_init(int port)
{
int sockfd;
struct sockaddr_in server_addr;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit(1);
}
printf("socket...\n");
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(port);
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1){
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
}
printf("bind...\n");
if(listen(sockfd,10)==-1){
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit(1);
}
printf("listen...\n");
return sockfd;
}
//protocol 协议
//-- head--- cmd data crc
//0x5a 0x15 0x-- 0x-- 0x--
int get_cmd(char * buf, char * cmd, int len)
{
char crc=0;
int i;
if(buf==NULL||cmd==NULL||len!=5) return -1;
if(buf[0]!=0x5a||buf[1]!=0x15)return -1;
for(i=0;i<len-1;i++){crc+=buf[i];}
if(crc!=buf[len-1])return -1;
cmd[0]=buf[2];
cmd[1]=buf[3];
return 0;
}
int send_cmd(char cmd, char cmd_da, int sockfd)
{
unsigned char buf[8];
if(sockfd<0)return -1;
buf[0]=0x5a;
buf[1]=0x15;
buf[2]=cmd;
buf[3]=cmd_da;
buf[4]=buf[0]+buf[1]+buf[2]+buf[3];
if(send(sockfd,buf,5,0)==-1){
fprintf(stderr,"Write error:%s\n",strerror(errno));
return -1;
}
return 0;
}
void *client_pro(void * arg)
{
int fd,*p;
int len,index;
int timer=0;
unsigned char recv_buf[8],cmd[8],old_cmd;
p=(int *)arg;
fd=*p;
net_user++;
index=net_user-1;
net_flag=1;//在线
g_dev_fd.net_fd[index]=fd;
old_cmd=net_cmd;//net_cmd的值在sw_pro线程中动态修改
while(1){
bzero(recv_buf,8);
bzero(cmd,8);
if(timer=3){//好方法,while循环中的定时器,3秒一次
timer=0;
send_cmd(0x10,0x11, fd);//查询设备是否在线
len=recv(fd,recv_buf,8,0);
if(len==0||len==-1){
net_user--;
close(fd);
net_flag=0;//下线
g_dev_fd.net_fd[index]=-1;
pthread_exit("0");
}else{
get_cmd(recv_buf,cmd,len);
if(cmd[0]==0x20&&cmd[1]==0x21)
net_flag=1;
else
net_flag=0;
printf("\nbuf=%x,%x,%x,%x,%x---cmd=%x,%x----\n",
recv_buf[0],recv_buf[1],recv_buf[2],recv_buf[3],recv_buf[4],cmd[0],cmd[1]);
}
}
if(old_cmd!=net_cmd){
old_cmd=net_cmd;
send_cmd(0x30,old_cmd,fd);//发送开关命令
}
sleep(1);
timer++;
}
}
void * net_pro(void * arg)
{
pthread_t pth;
int sockfd,new_fd,sin_size;
struct sockaddr_in client_addr;
printf("net server pthread start...\n");
sockfd=socket_init(DEF_PORT);
printf("sockfd=%d\n",sockfd);
while(1){
printf("accept before...\n");
sin_size=sizeof(struct sockaddr_in);
new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);
if(new_fd==-1){
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
pthread_exit("0");
}
//输出到屏幕,无缓冲,来一个字符就立马输出
fprintf(stderr,"Server from:%s\n\a",inet_ntoa(client_addr.sin_addr));
if(net_user<MAX_NET)
pthread_create(&pth,NULL,client_pro,(void*)&new_fd);
}
}