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);
}