CANoe-TCP/IP

CANoe的TCP/IP客户端网络通信

1, 通讯连接接口:
方法描述:实现Client模组与服务器建立连接,只在需要连接服务器的仪器start方法中调用一次。
方法参数:serverIP:服务器端IP地址;serverPort: 服务器端口
返回值: 0:连接成功;非0:连接失败,当连接失败的时候,在write窗口打印相关错误信息。
dword ConnectTcp(char serverIP[],int serverPort)

2, 通讯断开接口
方法描述:断开Client模组与服务器建立连接,在当前程控设备模组Stop方法中调用。
方法参数:空
返回值: 0:TCP断开成功;非0:断开失败,当连接失败的时候,在write窗口打印相关错误信息。
int DisconnectTcp()

3, 发送数据接口
方法描述:Client模组向服务器发送指定的一帧数据。
方法参数:buffer:一次发送的字符串数据
返回值: 0 发送成功;1 发送失败
int SendTcpData(char buffer[])

4, 接收数据接口
方法描述:数据接收为多线程事件驱动的方式,当socket会话的缓冲区中接收到数据 ,触发接收事件的发生。
方法参数:
Socket: 当前socket句柄
Result: The specific result code of the operation.
Address:IP地址
Port:端口
Buffer:当前接收到的数据
Size:当前接收到数据的长度
返回值: 空
void OnTcpReceive( dword socket, long result, dword address, dword port, char buffer[], dword size)
在这里插入图片描述
调用者只需要在具体的使用TCP/IP通讯的模组中调用以下接口方法
1、在调用的.can文件中赋值全局变量serverIP、serverPort

2、在调用的.can文件中定义系统变量sv_szRecvData,并让该系统变量指向为szRecvData,

3、调用ConnectTcp(serverIP,serverPort)连接服务器.成功返回值为0,不成功非0;

4、发送数据:调用SendTcpData(char buffer[])发送数据到server端,其中参数buffer为要发送的数据。

5、接收数据:系统变量sv_szRecvData就是每次缓冲区接收到的数据,在处理数据的时候,现在外面建立
全局的接收字符串,每次接收到缓冲区的数据后,累加到全局变量中,然后进行判断,当满足
接收完成条件后处理数据,处理完毕,再在全局变量中删除已经处理过的部分。

6、测试完成之后,调用DisconnectTcp()方法断开socket连接。
"TcpClient.can"代码

/*@!Encoding:936*/
includes
{
    
}

variables
{
    char absPath[128];
//  系统参数
  const long  INVALID_SOCKET =    ~0;
  const long  WSA_IO_PENDING =   997;
  const long  WSAEWOULDBLOCK = 10035;
  const dword INVALID_IP     = 0xffffffff;

  dword       gIpAddress           = INVALID_IP;
  char        gIpLastErrStr[1024]  = "";
  char        gIpAddressStr[32]    = "";
  int         gIpLastErr           = 0;

  dword       gUdpPort      = 0;
  long        gUdpSocket    = INVALID_SOCKET;
  char        gUdpRxBuffer[4096];

  dword       gTcpPort          = 0;
  long        gTcpSocket        = INVALID_SOCKET;
  long        gTcpDataSocket    = INVALID_SOCKET;
  char        gTcpRxBuffer[8192];

  // status
  int         gStatus = 0;
  const int   gkSTATUS_UNINITIALISED = 0;
  const int   gkSTATUS_INITIALISED   = 1;
    
  //客户端连接的服务端Ip地址
  char sz_ServerIp[64];
  //客户端连接的服务端端口地址
  int  g_u32_serverPort;
  //接收数据系统变量
  sysvarString * szRecvData;
  sysvarInt * OnTcpConnectFlag; 
    
  byte ReceiveOscBmpDatas[1152066];
  byte ReceiveOscBmp[1152066];
  byte OscBmpData[1152054];
}


//系统接收数据处理
long TcpRecv( dword socket)
{
  int result = 0;

  result = TcpReceive( socket, gTcpRxBuffer, elcount( gTcpRxBuffer));

  if ( 0 != result)
  {
    gIpLastErr = IpGetLastSocketError( socket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

      writelineex( 0, 2, "TcpReceive error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }

  return result;
}


//连接参数设置
void SetupIp()
{
  int   adapterIndex = 1;
  char  text[512] = "";
  char  info[512] = "";
  int   size = 512;
  long  result = 0;
  dword addresses[1];
  writeClear(0);
  if (1 > IpGetAdapterCount())
  {
    writelineex(0, 3, "Error: There is no network interface available!");
    
    stop();
  }

  if (0 != IpGetAdapterAddress(adapterIndex, addresses, 1))
  {
    writelineex(0, 3, "Error: Could not retrieve ip address!");
    
    stop();
  }

  gIpAddress = addresses[0]; // the interface used

  if (INVALID_IP == gIpAddress)
  {
    writelineex(0, 3, "Error: ip address to be used is invalid!");
    
    stop();
  }
 
  IpGetAdapterDescription(adapterIndex, text, size);
  snprintf(info, size, "Interface: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterAddressAsString(adapterIndex, text, size);
  snprintf(info, size, "Ip address: %s", text);
  writelineex(0, 1, info);

//  SysSetVariableString(sysvar::TCPIP::TcpClientIp, text);

  IpGetAdapterMaskAsString(adapterIndex, text, size);
  snprintf(info, size, "Subnet mask: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterGatewayAsString(adapterIndex, text, size);
  snprintf(info, size, "Gateway address: %s", text);
  writelineex(0, 1, info);
 
  gStatus = gkSTATUS_INITIALISED;
}

//启动方法 调用初始化参数
on start
{
  
  SetupIp(); 
   
}

on stopMeasurement
{
  DisconnectTcp();
}


//客户端接收数据处理方法
void OnTcpReceive( dword socket, long result, dword address, dword port, char buffer[], dword size)
{
  char  addressString[128] = "";
  
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpReceive called for unknown socket 0x%X", socket);

    return;
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpReceive error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);

    return;
  }
 
  IpGetAddressAsString(address, addressString, elcount(addressString));
  //将接收到的数据,赋给通用的匿名系统变量
  if(size > 0)
  {
    DataAlyse(buffer,size);
    TcpRecv(socket);
     //write("receiveTimer=%f",timeNow()/100.0);
  }

}

void DataAlyse(char buffer[],dword size)
{
  char picName[256] = "zlg.bmp";
  char picBuffer[256];
  //数据接收处理
  char  recvBuf[1024] = "";
    
  //图片处理  
  byte flag =0;
  long j=0,retSize=0;
  long i=0;
  dword glbHandle=0;
  
  if((buffer[0]=='#')&&(buffer[1]=='9')){
      flag=1; 
        j=0;
  }
  if(flag==1){
    for(i=0;i<elcount(buffer);i++){
      ReceiveOscBmp[j]=buffer[i];        
      j++;
      if(j==elcount(ReceiveOscBmp)){        
        if(ReceiveOscBmp[j-1]==0x0a){
            flag=0;
             //写入
            getAbsFilePath("",absPath,256);
            strncat(absPath,"Test\\ScopeImage",256);
            
            setFilePath(absPath, 2);//不可以直接设置C根目录,2表明可以对这个目录下的文件可读可写
//            setFilePath("C:\\Temp", 2);//不可以直接设置C根目录,2表明可以对这个目录下的文件可读可写
            sysGetVariableString(sysvar::Scope::sv_szSavePictureName,picBuffer,elCount(picBuffer));
            strncat(picBuffer,".bmp",256);
            
            glbHandle = openFileWrite (picBuffer,1); //1 ,表明是二进制方式打开文件写
	   //str_replace(picName,"zlg",picBuffer);
            
            //glbHandle = openFileWrite (picName,1); //1 ,表明是二进制方式打开文件写
            if ( glbHandle!=0 )
            {
                memcpy_off(OscBmpData,0,ReceiveOscBmp,11,elcount(OscBmpData));
                retSize = fileWriteBinaryBlock (OscBmpData, elcount(OscBmpData), glbHandle);
                fileClose (glbHandle);
            }
        }
        else{
            j=0;
            flag=0;
        }
      }  
    }
 }
  else{
      
    //接收到的不是图片数据
    if((size+1)>elcount(recvBuf)){
        write("Tcp_ScopeReceive Length =%d> recvBuf=%d ",size+1,elcount(recvBuf));
        write("Tcp_ScopeReceive Length =%s ",buffer);
    }
    strncpy(recvBuf,buffer,size+1);
    recvBuf[size] = '\0';
    sysSetVariableString(szRecvData, recvBuf);
    //write("szRecvData is %s",recvBuf);
  }
}

//系统数据发送
void OnTcpSend( dword socket, long result, char buffer[], dword size)
{
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpSend called for unknown socket 0x%X", socket);
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "HiokiScope/ZlgScope:OnTcpSend error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);
  }
}


//连接到服务器,只在需要连接服务器的仪器start方法中,调用一次。
//需传递参数为服务器端IP和端口
//返回值 0:连接成功;非0:连接失败
dword  ConnectTcp(char serverIP[],int serverPort)
{ 
   char buffer[64];
   dword serverIp;
    
   serverIp = IpGetAddressAsNumber(serverIP);
   gTcpDataSocket = TcpOpen(gIpAddress, gTcpPort);

  if (0 == TcpConnect(gTcpDataSocket, serverIp, serverPort))
  {
    writelineex(0, 1, "Successfully connected to server %s:%d", buffer, serverPort);
    return 0;
    TcpRecv( gTcpDataSocket);
    
  }
  return -1;
  //return gTcpDataSocket;
}


//断开TCP连接
//返回值 0:TCP断开成功;非0:断开失败
int DisconnectTcp()
{
  int result;
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    result = TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
    
    writelineex(0, 1, "Tcp socket is closed.");
  }
  return result;
}


//客户端向服务端发送数据
//参数为需要发送的数据
//返回值result:0 发送成功;1 发送失败
int SendTcpData(char buffer[])
{
  
  int result= 1;
  //write("SendingTimer=%f",timeNow()/100.0);
  if (0 != TcpSend( gTcpDataSocket, buffer, strlen(buffer)))
  {
    
    gIpLastErr = IpGetLastSocketError( gTcpDataSocket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( gTcpDataSocket, gIpLastErrStr, elcount( gIpLastErrStr));

      //writelineex( 0, 2, "HiokiScope/ZlgScope:Tcp send error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }
  else
  {
    //write("SendedTimer=%f",timeNow()/100.0);
    result = 0;
    //writelineex( 0, 1, "Tcp data sent successfully!");
  }

  return result;
}


void ResetIp()
{
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
  }
}



void OnTcpConnect( dword socket, long result)
{
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpConnect called for unknown socket 0x%X", socket);

    return;
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpConnect error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);

    return;
  }
  else
  {
    writelineex(0, 1, "Successfully connected to server via Tcp");
    sysSetVariableInt(OnTcpConnectFlag,1); // form 2
    TcpRecv( socket);
  }
}

主程序代码:

includes
{
    #include "TcpClient.can"
}

on start
{
  szRecvData = sysvar::Hardware::AuxPower::sv_szTcpDataRecv;
  ConnectTcp("192.168.1.23", 1798);
}
on key 'o'
{
	SendTcpData("OUTP ON\r\n");//ON
}
on key 'g'
{
	SendTcpData("MEAS:VOLT?\r\n");//查询真实电压
}

on sysvar sysvar::Hardware::AuxPower_DH1798::sv_szTcpDataRecv
{
  	char recvData[1024];
  	sysGetVariableString(this, recvData, elCount(recvData));
  	
  	@sysvar::Hardware::AuxPower::f64RealVolt= atodbl(recvData);
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜉蚁撼树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值