【计算机网络课程设计】2019-智能家居协议设计

题目描述:

  1. 智能家居协议设计

    实现一个基于socket的物联网服务器,接收来自客户端的数据。实现一个物联网客户端,模拟设备。客户端产生数据,发送至服务器,服务器根据协议对数据作出处理。

需要模式的设备有:

   温度传感器:采集房间温度信息。

   湿度传感器:采集房间湿度信息。

   空调:可以根据服务器发来的指令进行调节模式(制冷、制热、送风)、设置温度、风速;还可以根据服务器的指令上传子自己的当前状态:模式、温度、风速。

   门窗磁:可以根据服务器发来的指令打开或者关闭窗户。

要求:

   设计通信协议完成数据的双向传输,应用层协议应包含首部和数据部分。


学校:烟台大学计算机与控制工程学院2017级

完成时间:2019.12

老师:赵老师


具体实现过程参考附带的链接资源,此处只提供源码和一些实验指导,因为已经是放寒假已经半个月了,所以博客写的有些时间久远,大部分思路是在链接资源的实验报告里面:

CSDN资源:https://download.csdn.net/my

百度云:链接:https://pan.baidu.com/s/1DBFi4i2g1lL3MoQC6MQAGA 
提取码:54hx 

压缩包里面还有个一复杂版本的,那是我原来从GitHub上找的demo,比较完整,而且实现一些死锁问题的解决方案。


本次实验时间还是比较长的。但是实验还是比较匆忙的完成,因为大家都是提前验收的,没有考虑一些像是死锁一样的问题。


server.cpp

#include
#include
#include
#include
#include
using namespace std;
#pragma comment(lib, "ws2_32.lib")
char recv_buf[100];
char send_buf[100];

void print(char *s)
{
    int t, p;
    if(s[3] == '0'){  //温度传感器
        p = 0;
        t = 6;
        int tem;    // 温度
        int start_num = s[4] - '0';
        int num = s[5] - '0';
        cout<<"------------------------------------"<         cout<<"收到来自"<         while(num--){
            tem = 0;
            tem += (s[t++] - '0')*10;
            tem += (s[t++] - '0');
            cout<             p++;
        }
        cout<<"\n------------------------------------"<     }
    else if(s[3] == '1'){ //湿度传感器
        p = 0;
        t = 6;
        int shidu;    // 湿度
        int start_num = s[4] - '0';
        int num = s[5] - '0';
        cout<<"收到来自"<         while(num--){
            shidu = 0;
            shidu += (s[t++] - '0')*10;
            shidu += (s[t++] - '0');
            cout<             p++;
        }
    }
    cout<     return ;
}

int main()
{

    WORD wsa = MAKEWORD(2,2);
    WSADATA wsaData;
    if(WSAStartup(wsa, &wsaData)!=0)
    {
        cout<<"初始化失败"<         return 0;
    }
    //创建套接字
    SOCKET s_server = socket(AF_INET, SOCK_STREAM, 0);
    //AF_INET   面向网络的  IPV4
    //AF_INET6用于第6版因特网协议(IPv6)寻址
    //SOCK_STREAM   TCP链接   面向链接    SOCK_DGRAM 无连接 UDP
    if(s_server==INVALID_SOCKET) //INVALID_SOCKET是-1 错误标志
    {
        cout<<"socket创建失败"<         return 0;
    }
    //这里配置server配置信息
    sockaddr_in server_addr;    //创建sockaddr_in结构体
    server_addr.sin_family = AF_INET;   //IPV4协议
    server_addr.sin_port = htons(8888);     //本地端口8888
    server_addr.sin_addr.S_un.S_addr = INADDR_ANY;   //设置地址 监听本地端口
    //利用bind函数将socket和配置信息绑定
    //bind通常和下面的listen配套使用 处于被动链接中泰
    if   (  bind( s_server,(SOCKADDR *)&server_addr,sizeof(SOCKADDR)) ==SOCKET_ERROR )
    {
        //socket和配置绑定
        cout<<"ERROR bind!!"<         WSACleanup();
    }

    if(listen( s_server,5 )<0)
    {
        cout<<"监听失败"<     }
    cout<<"监听链接请求~~~"<     sockaddr_in clinet_addr;   //用于获取客户端地址端口信息 用于回传
    SOCKET s_accept;
    //这里定义了一个用于接收的sockaddr_in名字为s_accept。用于接收客户端的地址信息和端口信息,用于回传。
    int len=sizeof(SOCKADDR);
    s_accept = accept(s_server,(SOCKADDR *)&clinet_addr,&len);
    //在这里阻塞 挂起等待

    if( s_accept ==SOCKET_ERROR  )  //
    {
        cout<<"connect error"<         return 0;
    }
    cout<<"connection is OK;ready to accept"<     //两个buff缓冲区,用于缓存接收字符和发送字符。
    while(1)
    {

        int recv_len= recv(s_accept,recv_buf,100,0);
        //这里 即使链接断开 也能继续监听 服务端不关闭
        if(recv_len<0)
        {
            cout<<"服务器继续监听~~~~"<             s_accept = accept(s_server,(SOCKADDR *)&clinet_addr,&len);
            //客户端断开阻塞,挂起等待。在这里阻塞 挂起等待
            continue;
            if( s_accept ==SOCKET_ERROR  )  //
            {
                cout<<"connect error"<                 return 0;
            }
        }
        char recv_message[100];     //接收到的数据帧
        strcpy(recv_message,recv_buf);
        int message_len = strlen(recv_message);   //接收到的数据帧的长度

        print(recv_message);  //输出温度/湿度の状态

        char solid_head[] = {"5A"};   //固定头 帧头
        char function_num[] = {"0"};  //S-->C
        char device_type[3];          //设备类型,0-空调,1-门窗磁
        //判断空调
        if(recv_message[3] == '0' || recv_message[3] == '1')
            device_type[0] = '0'; // 0代表空调
        device_type[1] = '\0';
        char device_start[] = {"F"};  //不用  不使用
        char device_num[] = {"F"};    //不用
        strcat(send_buf,solid_head);
        strcat(send_buf,function_num);
        strcat(send_buf,device_type);
        strcat(send_buf,device_start);
        strcat(send_buf,device_num);
        int p;
        if(recv_message[3] == '0'){      //发来的是温度
            cout<<"调节空调温度,发送数据帧:";
            p = 6;
            int temsensor_num = recv_message[5] - '0';
            int temperature = 0;
            while(temsensor_num--){
                temperature += (recv_message[p++] - '0')*10;
                temperature += (recv_message[p++] - '0');
            }
            temperature /= (recv_message[5] - '0');  //空调模式
            if(temperature<18){
                char moshi[] = {"1"}; //制热
                char tem_standard[] = {"18"};
                char wind_speed[] = {"1"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
            else if(temperature>18){
                char moshi[] = {"0"}; //制冷
                char tem_standard[] = {"18"};
                char wind_speed[] = {"1"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
            else{
                char moshi[] = {"2"}; //送风
                char tem_standard[] = {"18"};
                char wind_speed[] = {"0"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
        }
        if(recv_message[3] == '1'){      //发来的是湿度
            cout<<"调节空调湿度,发送数据帧:";
            p = 6;
            int humsensor_num = recv_message[5] - '0';
            int humperature = 0;
            while(humsensor_num--){
                humperature += (recv_message[p++] - '0')*10;
                humperature += (recv_message[p++] - '0');
            }
            humperature /= (recv_message[5] - '0');
            if(humperature<30){
                char moshi[] = {"3"}; //提高湿度
                char tem_standard[] = {"30"};
                char wind_speed[] = {"1"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
            else if(humperature>30){
                char moshi[] = {"4"}; //降低湿度
                char tem_standard[] = {"30"};
                char wind_speed[] = {"1"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
            else{
                char moshi[] = {"2"}; //送风
                char tem_standard[] = {"30"};
                char wind_speed[] = {"0"};
                strcat(send_buf,moshi);
                strcat(send_buf,tem_standard);
                strcat(send_buf,wind_speed);
            }
        }
        //判断门窗锁
        //cout<         send(s_accept,send_buf,100,0);
        send_buf[3] = '1'; //此时设备为门窗磁
        if(recv_message[3] == '0' || recv_message[3] == '1'){
            cout<<"调节门窗,发送数据帧:";
            p = 6;
            int temsensor_num = recv_message[5] - '0';
            int temperature = 0;
            while(temsensor_num--){
                temperature += (recv_message[p++] - '0')*10;
                temperature += (recv_message[p++] - '0');
            }
            temperature /= (recv_message[5] - '0');
            if(temperature > 18){
                send_buf[6] = '0';   //门窗关闭
            }
            else{
                send_buf[6] = '1';   //门窗打开
            }
            send_buf[7] = 'F';
            send_buf[8] = 'F';
            send_buf[9] = 'F';
        }
        send(s_accept,send_buf,100,0);
        cout<         memset(send_buf,0,sizeof(send_buf));
        cout<<"发送成功"<

    }
    closesocket(s_server);
    closesocket(s_accept);
    //释放DLL资源
    WSACleanup();
    return 0;
}

/*
5A00121723, 10
输入服务端消息
456
发送成功

5A00311723, 10
输入服务端消息
*/
 


client.cpp

#include
#include
#include
#include
#include
#include
#define random(a,b) (rand()%(b-a)+a)
#pragma comment(lib, "WS2_32")
using namespace std;


char send_buf[200];     //发送数据报
char accept_buf[200];   //接受数据报
string strtem(int i);   //生成随机温度数据段
string strhum(int i);   //生成随机湿度数据段
void tcpxy();           //生成上传服务器报文
void analysis(char receive[]);  //对服务器传回的报文进行解析

int main()
{

    WORD wsa = MAKEWORD(2,2);
    WSADATA wsaData;
    //WSADATA结构体中主要包含了系统所支持的Winsock版本信息  WSA API
    if(WSAStartup(wsa, &wsaData)!=0)
    {
        cout<<"初始化失败"<         return 0;
    }
    SOCKET s_server = socket(AF_INET, SOCK_STREAM, 0);
    if(s_server==INVALID_SOCKET)
    {
        cout<<"socket创建失败"<         return 0;
    }
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;       //IPV4协议
    server_addr.sin_port = htons(8888);     //服务器端口
    server_addr.sin_addr.S_un.S_addr = inet_addr("192.168.43.15");  //服务器IP
    if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)  //链接失败
    {
        cout << "server connnet fail!!" << endl;
        WSACleanup();
        return 0;
    }
    else
    {
        cout << "服务器连接成功!" << endl<     }
    Sleep(1*1000);
    cout<<"开始上传温度和湿度传感器信息..."<

    while(1)
    {
        cout<<"上传服务器报文为:"<         tcpxy();

        //cout<         // cin>>send_buf;//生成当前传感器状态。
        //cout<<"发送的"<         int res_len = send(s_server,send_buf,100,0);
        if(res_len<0)
        {
            cout<<"error"<             return 0;
        }
        cout<<"报文发送成功,等待接受"<         recv(s_server, accept_buf, 200, 0);
        cout<<"收到服务器端消息";
        analysis(accept_buf);
        Sleep(1*1000);
        cout<         recv(s_server, accept_buf, 200, 0);
        cout<<"收到服务器端消息";
        analysis(accept_buf);
        cout<<"------------------------------------------------"<         Sleep(3*1000);//延时3秒
    }

    closesocket(s_server);
    //释放DLL资源
    WSACleanup();
    return 0;
}

void analysis(char receive[])  //解析
{
    cout<<"传输的报文为:"<     cout<<"报文解析结果为:"< //    for(int i=0;i //        cout< //    cout<     int rev_length=strlen(receive);
    if(receive[2]=='1')
    {
        cout<<"当前室内温度为:"<     }
    else if(receive[2]=='0')
    {
        string strp1;
        string strp2;
        string strp3;
        string strp4;
        string strp5;
        if(receive[7]=='1'&&receive[8]=='8')
            strp3="温度为:18%";
        else if(receive[7]=='3'&&receive[8]=='0')
            strp3="湿度为:30%";
        //cout<<"服务器发送的指令为:"<         if(receive[3]=='0')
        {
            strp1="空调";
            if(receive[6]=='0')
            {
                strp2="制冷";
            }
            else if(receive[6]=='1')
            {
                strp2="制热";
            }
            else if(receive[6]=='2')
            {
                strp2="送风";
            }
            else if(receive[6]=='3')
            {
                strp2="提湿度";
            }
            else if(receive[6]=='4')
            {
                strp2="减湿度";
            }
            if(receive[9]=='0')
            {
                strp4="慢风速";
            }
            else if(receive[9]=='1')
            {
                strp4="中风速";
            }
            else if(receive[9]=='2')
            {
                strp4="高风速";
            }
            cout<         }
        else if(receive[3]=='1')
        {
            strp1="门窗磁";
            if(receive[6]=='0')
                strp5="开窗";
            else if(receive[6]=='1')
            {
                strp5="关窗";
            }
            cout<         }


    }
}


void tcpxy()
{

    memset(send_buf,0,sizeof(send_buf));
    // memset(accept_buf,0,sizeof(accept_buf));
    int j=0;
    srand((int)time(0));  // 产生随机种子  把0换成NULL也行
    int devicebnum=random(0,2);  //设备类型 0 温度,1 湿度
    int tempnum=random(1,5);//温度反应器数量
    int humnum=random(1,5);//湿度感应器数量
    int startnum=random(1,5);
    int direction=1;//1表示客户端到服务器,0表示服务器到客户端
    string stableheader="5A";
    if(startnum==1)
    {
        tempnum=random(1,5);
        humnum=random(1,5);
    }
    else if(startnum==2)
    {
        tempnum=random(1,5);
        humnum=random(1,5);
    }
    else if(startnum==3)
    {
        tempnum=random(1,3);
        humnum=random(1,3);
    }
    else
    {
        tempnum=1;
        humnum=1;
    }
    string str3 = to_string(devicebnum);
    string str4 = to_string(tempnum);
    string str5 = to_string(humnum);
    string str6 = to_string(startnum);
    string str7 = to_string(direction);
    string str=stableheader+str7+str3+str6+str4; //帧格式:帧头+发送方向+设备类型+开始编号+数量+数据段
    if(devicebnum==0)
        str+=strtem(tempnum);
    else if(devicebnum==1)
        str+=strhum(tempnum);
    cout<     // cout<

    for(int i=0; i     {
        send_buf[j]=str[i];
        j++;
    }
    char qishi=send_buf[4];
    char shebinum=send_buf[5];
//    if(send_buf[3]=='0')
//    {
//        strp1="温度传感器温度分别为:";
//    }
//    else if(send_buf[3]=='1')
//    {
//        strp1="湿度传感器湿度分别为:"
//    }
//    cout<<"当前房间"+strp1+
}
string strtem(int i)//生成随机温度数据段
{
    int temperature;
    string str;
    for(int j=0; j     {
        temperature=random(15,26);//产生随机温度。
        str+=to_string(temperature);
    }
    return str;
}
string strhum(int i)//生成随机湿度数据段
{
    int humidity;
    string str;
    for(int j=0; j     {
        humidity=random(25,46);//产生随机湿度。
        str+=to_string(humidity);
    }
    return str;
}
 


最重要的是感谢周学长和虎 学长o(╥﹏╥)o,原来找的那个demo太大太难了,入手慢,感谢o(╥﹏╥)o

你可能感兴趣的:(YTUの课设,计算机网络)