• C语言 udp通信


    // serv.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    #include <STDIO.H>    
    #include <STDLIB.H>    
    #include     
    #pragma comment (lib, "ws2_32.lib")

    #include
    #include
    #pragma comment(lib,"Winmm.lib")

    void ReiveData();
    HANDLE hThreadHandle_page1;
    DWORD  dwThreadID_page1;
    int fromlen;
    int sendlen;
    SOCKET socket1;
    SOCKET socket2;
    struct sockaddr_in client1;   
    struct sockaddr_in client2;


    /*
    仿真机与DCS双向发送的数据包格式相同,都由16字节的头部和最长1200字节的数据区构成。以下定义各字段字节数均按32位平台计算。
    头部定义如下:
    域号,unsigned char,仿真机向DPU发送数据时,是目标站的域号。如果目标站是全部DPU,填0xFF。当DPU向仿真机发送数据时,是源站(DPU)的域号。
    站号,unsigned char,仿真机向DPU发送数据时,是目标站的站号。如果目标站是全部DPU,填0xFF。当DPU向仿真机发送数据时,是源站(DPU)的站号。
    字节序标志,unsigned char,对于X86平台,等于1。
    包类型,unsigned char,实时数据=128,命令=129,命令回应=130。
    秒,unsigned long,代表数据发送时刻的数值(C函数time()的返回值)。
    毫秒,unsigned short,数据发送时刻的毫秒部分。
    CRC,unsigned short,数据区的CRC16校验值。
    数据区长度,unsigned short,数据区的实际字节数(不含头部)。
    数据包流水号,unsigned short,为过滤重复数据包,每包可给定不同的数字。
    其中时间、CRC和数据包流水号可选。暂时可不处理这几项数据。
    数据区是模拟量或开关量的实时数据,每个点占用8字节,两种数据可混合排放。每个点定义如下:
    点ID,unsigned int,对照表规定了每个点的ID。
    数值,float/int,由点ID确定点记录后,根据类型(模拟/开关)把数值部分的4字节解释为浮点数或整数。如果是开关点,整数是0或1。
    根据以上定义,每个数据包最多容纳150个点记录的数据。
    */
    typedef struct {    
        unsigned int ID;
        char simbuff[4];
       } DATAFIELD;
    typedef struct
    {
        unsigned char domainname;  //1byte 1
        unsigned char stationid;   //1byte 2
        unsigned char byteflag;    //1byte 3
        unsigned char datatype;    //1byte 4  
        unsigned long second;      //4byte 8
        unsigned short milsecond;  //2byte 10
        unsigned short CRC16;      //2byte 12
        unsigned short databyte;   //2byte 14
        unsigned short datanum;   // 2byte 16  共16字节
        DATAFIELD data[150];
    }SIMDATA;
    typedef struct
    {
        unsigned char domainname;
        unsigned char stationid;
        unsigned char byteflag;
        unsigned char datatype;
        unsigned long second;
        unsigned short milsecond;  
        unsigned short CRC16;
        unsigned short databyte;
        unsigned short datanum;
        int cmd;  //命令
        unsigned int  parm1 ;//参数1
        long parm2; //参数2
    }CMDDATA;
    /*
    命令和参数定义如下:
    命令    含义    参数1    参数2
    1    运行/冻结    1运行,0冻结    忽略
    2    抽点/回退    1回退,0抽点    组号
    3    初始条件保存和加载    1保存条件,0加载条件     组号
    4    抽点文件保存和加载    1保存,0加载    组号
    5    删除所有抽点文件    忽略    忽略
    6    删除所有初始条件    忽略    忽略
    7    按参数判断删除那种文件
        0:删除初始文件

    1:删除抽点文件    仅当参数1等于0有效
    -1:删除所有的初始文件
    大于等于0的数字:要删除的初始文件组号。
    */

    typedef struct
    {
        unsigned char domainname;  
        unsigned char stationid;
        unsigned char byteflag;
        unsigned char datatype;
        unsigned long second;
        unsigned short milsecond;  
        unsigned short CRC16;
        unsigned short databyte;
        unsigned short datanum;
        int cmd ;
        int error;
    }CMDDATA_DCS;
    /*
    数值    含义
    0    成功
    1    指令或参数无效
    2    指定文件不存在
    3    访问指定文件出错(无访问权限,文件内容错误等)
    */
    //SIMDATA simdata;
    //CMDDATA_DCS simcmd;


    int    o_num ;
    int i_num ;
    int ao_num ;
    int do_num ;
    int    di_num ;
    int    ai_num ;
    #define REAL    1
    #define FLOAT   2
    #define LONG    3
    #define SHORT   4
    #define INT     5
    #define LOG     6
    #define DOUBLE  7
    #define DOUBLE2  8
    #define S3_VARLEN   48
    typedef union {    
        double  r8;
        float   r4;
        int     i4;
         double i8;
        short   i2;
        char    i1;
       } VAL;/*from s3_parm.h variable value*/
    typedef char VAR[S3_VARLEN] ; /*variable name*/
    typedef struct
    {
        VAR varname;
        int index;
        char *vaddress;
        VAL  oldvarvalue;
        char type1; //r,i,
        char type2; //r,i,
        char vartype;
    }DATA;
    typedef struct
    {
        int index; /* the order of variable in the picture*/
        char vartype;
      VAL varvalue;
    }getdata;
    #define AO 1
    #define DO 2
    #define AI 3
    #define DI 4
    #define pr
    #define MAXIN 10240
    #define MAXOUT 20480//10240
    #define INLEN 16*MAXIN+8
    #define OUTLEN 16*MAXOUT+8
    DATA data_i[MAXIN];
    DATA data_o[MAXOUT];
    getdata val_i[MAXIN];
    getdata val_o[MAXOUT];
    float fgsevalue[MAXOUT];
    int igsevalue[MAXOUT];
    //

    float global_floatdata[100];
    float sim_data[150];
    unsigned char simbuff[1216];
    char m_buffer[1216];
    char send_buffer[28];
    char simbuff_cmd[28];
    char cmd_buffer[28];
    int all_data_count;
    int count150;
    SIMDATA simdata;
    CMDDATA simcmd;

    #define DATA_RECEIVE_LEN 1216    //数据包
    char rev_buffer[DATA_RECEIVE_LEN];
    unsigned char rev_data[DATA_RECEIVE_LEN];
    unsigned char revbuff[DATA_RECEIVE_LEN];
    float global_revdata[100];
    int cmd;
    unsigned int parm1;
    long parm2;
    SIMDATA revdata;
    CMDDATA_DCS revcmd;


    int InitSocket(); //初始化套接字
    void SendParametorDataByTimer( ); //发送参数信息,以一定时间间隔,如0.1秒或1秒等
    void SendCommandDataChange( );  //发送命令信息,当命令字发生变化
    void buildData_Head(); //建立数据头数据
    void buildData_CMDHead(); //建立命令头数据
    void GetRealValue(); //获取实时值
    void ReceiveCommandDataChange( );  //接收DCS命令信息,当命令字发生变化
    void buildData_Head() //建立数据头数据
    {
        simdata.domainname = 0xFF;
        simdata.stationid = 0xFF;
        simdata.byteflag = 1;
        simdata.datatype = 128;
        simdata.second = 128;
        simdata.milsecond = 1;
        simdata.CRC16 = 0;
        simdata.databyte =1200;
        simdata.datanum = 0;
     }


    void buildData_CMDHead() //建立命令头数据
    {
        simcmd.domainname = 0xFF;
        simcmd.stationid = 0xFF;
        simcmd.byteflag = 1;
        simcmd.datatype = 129;
        simcmd.second = 128;
        simcmd.milsecond = 1;
        simcmd.CRC16 = 0;
        simcmd.databyte =12;
        simcmd.datanum = 0;
     }
    /************************************************************************************************************
                 GetAddrFromDBM
    *************************************************************************************************************/

    void GetRealValue() //获取实时值
    {   
        
          int ista,i,j;  

       // for( i=0;i       for( i=0;i     {   
           //memcpy(&fgsevalue[i],data_o[i].vaddress+4*i,4);
           fgsevalue[i] = i*10.;
           //printf("fgsevalue %f i= %d  \n", fgsevalue[i], i );
        }   
              printf("finished get real time value.\n");
    }
    void ReiveData()
    {
        int i;
        float gsedata[150];

        while (1)   
        {     
            printf("waiting for message from others-------------\n");   
            if (recvfrom(socket1,rev_buffer,sizeof(rev_buffer),0,(struct sockaddr*)&client1,&sendlen)!=SOCKET_ERROR)   
            {   
                 memcpy(&revbuff,rev_buffer,sizeof(rev_buffer));

                 memcpy(&revdata.domainname, &revbuff[0], sizeof(char));
                 memcpy(&revdata.stationid,  &revbuff[1], sizeof(char));
                 memcpy(&revdata.byteflag,   &revbuff[2], sizeof(char));
                 memcpy(&revdata.datatype,   &revbuff[3], sizeof(char));
                 memcpy(&revdata.second,     &revbuff[4], 4*sizeof(char));
                 memcpy(&revdata.milsecond,  &revbuff[8], 2*sizeof(char));
                 memcpy(&revdata.CRC16,      &revbuff[10], 2*sizeof(char));
                 memcpy(&revdata.databyte,   &revbuff[12], 2*sizeof(char));
                 memcpy(&revdata.datanum,    &revbuff[14], 2*sizeof(char));

                 printf("%d  simdata.databyte \n",revdata.databyte);

                 int value = revdata.databyte;
          if(value == 1200){
                 memcpy(&revdata.data,   &revbuff[16], 1200*sizeof(char));
                 for (i = 0;i<150;i++)
                 {
                     memcpy( &gsedata[i] ,&revdata.data[i].simbuff, 4*sizeof(char) );
                    // printf( "gsedata i = %d  value = %f \n",i, gsedata[i]);
                 }
               //  printf("%x  revdata.domainname \n",revdata.domainname);
                // printf("%x  revdata.stationid \n",revdata.stationid);
                // printf("%x  revdata.byteflag \n",revdata.byteflag);
                // printf("%x  revdata.datatype \n",revdata.datatype);
                //  printf("%d  revdata.second \n",revdata.second);
                  printf("%d  simdata.databyte \n",revdata.databyte);
                  printf("%d  simdata.datanum \n",revdata.datanum);

                  printf("--------------------------------\n");
                 // printf("revdata.data.ID %d \n",revdata.data[0].ID);

                 // printf("revdata.data.simbuff %f \n",revdata.data[0].simbuff);

                 // printf("revdata.data.ID %d \n",revdata.data[2].ID);
               //   printf("revdata.data.simbuff %f \n",revdata.data[2].simbuff);
          }
          else if ( value == 12){
                  memcpy(&cmd,   &revbuff[16], 4*sizeof(char));
                  memcpy(&parm1,   &revbuff[20], 4*sizeof(char));
                  memcpy(&parm2,   &revbuff[24], 4*sizeof(char));
                  printf("cmd ****** %d \n",cmd);
                  printf("parm1 ****** %d \n",parm1);
                  printf("parm2 ****** %d \n",parm2);
          }
            }   
               
        }   
        closesocket(socket1);       
    }
    void SendParametorDataByTimer( )  //发送参数信息,以一定时间间隔,如0.1秒或1秒等
    {   int i,j;
        bool m_nThreadStatus = true;
        memset(m_buffer, 0, sizeof(m_buffer));
        all_data_count = 1500;

        //while( m_nThreadStatus )
        {

             GetRealValue(); //获取实时运行数据
    /***************************仿真数据包********************/
             buildData_Head();//封装数据包头

             //all_data_count = ao_num+do_num;
            //仿真数据
            if( all_data_count< 150)
            {
                 for (i=0;i              {
                    simdata.data[i].ID = data_o[i].index;
                    sim_data[i] = fgsevalue[i];
                    memcpy( simdata.data[i].simbuff,&sim_data[i],4*sizeof(char));
                    
                 }
                 for (i=all_data_count;i<150;i++) //填充无用数据
                 {
                    simdata.data[i].ID = 200000;
                    sim_data[i] = 0;
                    memcpy( simdata.data[i].simbuff,&sim_data[i],4*sizeof(char));
                    
                 }
              memcpy(simbuff, &simdata, sizeof(SIMDATA));
              memcpy(m_buffer,simbuff,sizeof(simbuff));
             if( sendto(socket1,m_buffer,sizeof(m_buffer),0,(struct sockaddr*)&client2,sendlen)!=SOCKET_ERROR)
             {  
                printf("sending data successly ..\n");
             }
            }
              //>150或者为其整数倍
                count150 = (int)(all_data_count/150.);
                for(j = 0;j< count150;j++)
               {
                   simdata.datanum = j+1;
                 for (i=0;i<150;i++)
                 {
                    simdata.data[i].ID = data_o[i+j*150].index;
                    sim_data[i] = fgsevalue[i+j*150];
                    memcpy( simdata.data[i].simbuff,&sim_data[i],4*sizeof(char));
                    
                 }
                    simcmd.datanum = j+1;
                    memcpy(simbuff, &simdata, sizeof(SIMDATA));
                    memcpy(m_buffer,simbuff,sizeof(simbuff));
                    if( sendto(socket1,m_buffer,sizeof(m_buffer),0,(struct sockaddr*)&client2,sendlen)!=SOCKET_ERROR)
                   {  
                       printf("sending data successly ..\n");
                     }
                }
                
             //Sleep(1000);                
        }
         //closesocket (socket2);
        
    }
    void SendCommandDataChange( )  //发送命令信息,当命令字发生变化
    {
        int i;
        bool m_nThreadStatus = true;
        //memset(cmd_buffer, 0, sizeof(cmd_buffer));
        //while( m_nThreadStatus )
        {

            /*命令数据包*/
             buildData_CMDHead();
             simcmd.cmd = 1;
             simcmd.parm1 = 1;
             simcmd.parm2 = 0;
             if(simcmd.datanum == 0 )
                 simcmd.datanum = 1;
             else
                 simcmd.datanum = 0;
            memcpy(simbuff_cmd, &simcmd, sizeof(CMDDATA));
          
            memcpy(cmd_buffer,simbuff_cmd,sizeof(simbuff_cmd));
            if( sendto(socket2,cmd_buffer,sizeof(cmd_buffer),0,(struct sockaddr*)&client2,sendlen)!=SOCKET_ERROR)
            {  
                printf("sending data successly ..\n");
             }

            //Sleep(1000);    
         }
          //closesocket (socket2);
    }

    // add by ch

    const int MAX_KEY_NUM = 128;
    const int MAX_KEY_LENGTH = 1024;

    char gKeys[MAX_KEY_NUM][MAX_KEY_LENGTH];

    char *GetIniKeyString(char *title, char *key, char *filename)
    {
        FILE *fp;
        int  flag = 0;
        char sTitle[32], *wTmp;
        char sLine[MAX_KEY_LENGTH];

        sprintf(sTitle, "[%s]", title);
        if (NULL == (fp = fopen(filename, "r")))
        {
            perror("fopen");
            return NULL;
        }

        while (NULL != fgets(sLine, MAX_KEY_LENGTH, fp))
        {
            /// 这是注释行  ///
            if (0 == strncmp("//", sLine, 2)) continue;
            if ('#' == sLine[0])              continue;

            wTmp = strchr(sLine, '=');
            if ((NULL != wTmp) && (1 == flag))
            {
                if (0 == strncmp(key, sLine, wTmp - sLine))  /// 长度依文件读取的为准  ///
                {
                    sLine[strlen(sLine) - 1] = '\0';
                    fclose(fp);
                    return wTmp + 1;
                }
            }
            else
            {
                if (0 == strncmp(sTitle, sLine, strlen(sLine) - 1))  /// 长度依文件读取的为准  ///
                {
                    flag = 1; /// 找到标题位置  ///
                }
            }
        }
        fclose(fp);
        return NULL;
    }

    void WINAPI onTimeCommand(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2);  

    void WINAPI onTimeCommand(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)  
    {  
        printf("onTimeCommand do ...\n");  
        SendCommandDataChange();
        return;  
    }

    void WINAPI onTimePara(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2);  

    void WINAPI onTimePara(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)  
    {  
        printf("onTimePara do ...\n");  
        SendParametorDataByTimer();
        return;  
    }

    //开启2个定时器
    void startTimer()
    {

        char * timeCommand =  (char*)malloc(100 * sizeof(char));
        strcpy(timeCommand,GetIniKeyString("Timer", "timeCommand", "config.ini"));    
        printf("timeCommand is %s\n", timeCommand);

        MMRESULT timer_command;  
        timer_command = timeSetEvent(atoi(timeCommand), 1, (LPTIMECALLBACK)onTimeCommand, DWORD(1), TIME_PERIODIC);   

         if(NULL == timer_command)  
        {  
            printf("timeSetEvent()timer_command  failed with error %d/n", GetLastError());  
            return ;  
        }


         char * timePara =  (char*)malloc(100 * sizeof(char));
        strcpy(timePara,GetIniKeyString("Timer", "timePara", "config.ini"));    
        printf("timePara is %s\n", timePara);

         MMRESULT timer_para;  
        timer_para = timeSetEvent(atoi(timePara), 1, (LPTIMECALLBACK)onTimePara, DWORD(1), TIME_PERIODIC);   

         if(NULL == timer_para)  
        {  
            printf("timeSetEvent() timer_para failed with error %d/n", GetLastError());  
            return ;  
        }

    }

    // add by ch

    int _tmain(int argc, _TCHAR* argv[])
    {

        WSADATA wsaData;   

        if (WSAStartup(MAKEWORD(2,1),&wsaData)) //调用Windows Sockets DLL    
        {    
            printf("Winsock无法初始化!\n");   
            WSACleanup();   
            return 0;   
        }   
           
        printf("服务器开始创建SOCKET。\n");   
     

        //读取配置文件开始

        char * ipOne =  (char*)malloc(100 * sizeof(char));
        strcpy(ipOne,GetIniKeyString("IPSite", "socketOneIp", "config.ini"));    
        printf("ipOne is %s\n", ipOne);

        char * portOne  =  (char*)malloc(100 * sizeof(char));
        strcpy(portOne,GetIniKeyString("IPSite", "socketOnePort", "config.ini"));
        printf("portOne is %s\n", portOne);

        char * ipTwo  =  (char*)malloc(100 * sizeof(char));
        strcpy(ipTwo,GetIniKeyString("IPSite", "socketTwoIp", "config.ini"));
        printf("ipTwo is %s\n", ipTwo);

        char * portTwo  =  (char*)malloc(100 * sizeof(char));
        strcpy(portTwo,GetIniKeyString("IPSite", "socketTwoPort", "config.ini"));
        printf("portTwo is %s\n", portTwo);

        //读取配置文件结束


         fromlen =sizeof(client1);   
        client1.sin_family=AF_INET;   
        client1.sin_port=htons(atoi(portOne)); ///监听端口      
        client1.sin_addr.s_addr=inet_addr(ipOne); ///server的地址
        
        socket1=socket(AF_INET,SOCK_DGRAM,0);   
        bind(socket1,(struct sockaddr*)&client1,sizeof(client1));

        sendlen =sizeof(client2);   
        client2.sin_family=AF_INET;   
        client2.sin_port=htons(atoi(portTwo)); ///监听端口      
        client2.sin_addr.s_addr=inet_addr(ipTwo); ///server的地址
        
        socket2=socket(AF_INET,SOCK_DGRAM,0);   
        //bind(socket2,(struct sockaddr*)&client2,sizeof(client2));

        startTimer(); // add by ch

       // ReiveData();
        SendParametorDataByTimer( );
        //SendCommandDataChange( );
        return 0;
    }

  • 相关阅读:
    facebook引流软件需要具备什么功能
    [轻笔记] SHAP值的计算步骤
    了不起的爸爸
    NC51316 Going Home (最大完美匹配)
    sp-踩坑小记
    FastDFS报错File name too long(fdfs报错File name too long)
    Node.js | 操作本地文件 — 玩转 fs 内置模块
    使用gitlab的cicd自动化部署vue项目shell流程踩坑之路
    Spark 平障录
    亚商投资顾问 早餐FM/12022023年开展第五次全国经济普查
  • 原文地址:https://blog.csdn.net/qq_14874791/article/details/134054503