我想使用以太网端口通过创建套接字发送数据。
如何打开以太网端口并设置 IP、NETMASK 和网关?我可以使用这些功能,但我不知道如何打开以太网端口或如何配置这些功能。
ceSETNWParamValue();
ceGetNWParamValue();
ceSetDDParamValue();
我想使用以太网端口通过创建套接字发送数据。
如何打开以太网端口并设置 IP、NETMASK 和网关?我可以使用这些功能,但我不知道如何打开以太网端口或如何配置这些功能。
ceSETNWParamValue();
ceGetNWParamValue();
ceSetDDParamValue();
好吧,“Verix eVo Volume II OS and Communication Programmers Guide”(特别是第 5 章)可以帮助您一点,但在我们开始之前,有一件重要的事情需要考虑 - 如果您正在使用这个程序您在 vx520 上编写,您可能希望在将来的某个时间点将它用于另一种终端类型。为此,您可以考虑使用 CommServer。CommServer 是一个帮助从代码中抽象出各种类型的硬件的程序,因此您可以将相同的命令发送到任何终端类型,并让它根据所使用的硬件确定如何满足您的请求。它已经存在了一段时间,并已移植到大多数 VerFone 终端类型。它由 VeriFone 免费提供(和支持)。它有几个缺点:
然而,一旦你让它工作,它真的很好:
很有可能在某个时候,您需要与另一个第 3 方共享您的终端。如果是这样的话,无论如何,你需要让你的程序在 VMAC 之上运行,而且他们很有可能也会使用 CommServer。如果是这种情况,那么 2 个“CON”就消失了,一个“PRO”只是被强调了。
所以现在你必须选择——CommServer,或者没有CommServer。
如果您选择 CommServer,则需要非常熟悉 FlexiRecords 的工作原理,因此作为先决条件,我建议您阅读“Verix eVo Multi-App Conductor Programmers Guide”的第 7 章。接下来,程序流程将如下所示:
1)初始化事件缓冲区
// Initializes the buffer provided to store a new flexi-record structure.
// This is a flexirecord public interface function.
vVarInitRecord(buffer, sizeof(buffer), 0);
// Assigns the buffer passed as a parameter to the global space of the Extended
// Flexi-record API.This is a mandatory function call for the rest of the Extended
// Flexi-record APIs.The buffer should be initialized using vVarInitRecord()
// function before calling this API.
ushInitStandardFlexi(buffer);
//send the event (you'll need some other boiler plate code)
// you'll probably want to turn this into a "SendEvent" method
EESL_send_event("COMMSVR", VCS_EVT_INIT_REQ, buffer, bufferSize);
// read the response from CommSever (again, this is a skeletal sample)
// This will become a "ReadEvent" method
while(strcmp(sendername, "COMMSVR") || eventID != VCS_EVT_INIT_RESP)
eventID = EESL_read_cust_evt(buffer, sizeof(buffer), &bufferSize, sendername);
2) 连接
vVarInitRecord(eco->Buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
// shVarAddData will add an un-typed field to a variable record
// The field VCS_FLD_CONN_URL is defined as a URL or an IP address to connect to.
// All syntax validation of URL or IP address is performed by the TCP/IP library.
shVarAddData(VCS_FLD_CONN_URL, hostip, strlen(hostip));
// shVarAddUnsignedInt adds (unsurprisingly) an unsigned int to the Flexi-record.
// The constant VCS_FLD_CONN_PORT defines the TCP/IP port number
shVarAddUnsignedInt(VCS_FLD_CONN_PORT, port);
// The value VCS_FLD_CONN_HOSTSSL represents a flag that indicates whether SSL
// is supported or not: (1 - SSL supported, 0 - SSL not supported)
shVarAddUnsignedInt(VCS_FLD_CONN_HOSTSSL, useSSL);
// (if you are going to use SSL, you'll need to add some other values, too)
//Honestly, I don't know what this is, but I don't think it works without it
shVarAddUnsignedInt(VCS_FLD_CONN_HOSTCTX, (unsigned short)0);
//send the event (you'll need some other boiler plate code)
EESL_send_event("COMMSVR", VCS_EVT_CONN_REQ, buffer, bufferSize);
// read the response from CommSever (use the same "receive" code from above,
// but you are looking for the response "VCS_EVT_CONN_RESP"
EESL_read_cust_evt(buffer, sizeof(buffer), &bufferSize, sendername);
3) 确认您已连接
vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
// Add Status ID buffer to the parameter list
shVarAddData(VCS_FLD_STATUS_IDS, (unsigned char*)statusIDs, (sizeof(int) * 2));
// do your "sendEvent" from above with the event VCS_EVT_STATUS_REQ
SendEvent(VCS_EVT_STATUS_REQ);
// do your "ReceiveEvent" from above, looking for VCS_EVT_STATUS_RESP
ReadEvent(VCS_EVT_STATUS_RESP);
// Extract data from event buffer
ushInitStandardFlexi(buffer);
//This is the eVo (520) version:
shVarGetUnsignedInt(VCS_FLD_CONN_STATUS, (unsigned short*)&connStatus);
//This is the Verix/Vx version
//shVarGetData(VCS_FLD_CONN_STATUS, (unsigned char*)&connStatus,
sizeof(unsigned short), &dataLength);
if (connStatus == 1) {/* you are connected */}
4) 发送
vVarInitRecord(eco->Buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
//Add length parameter to the data stack.
shVarAddUnsignedInt(VCS_FLD_SEND_BUFSIZE, p_size);
// Send Event to server. Note that this doesn't actually send the data, it simply
// tells CommServer that data will be coming shortly. It also advises the length
// of the data to be sent
SendEvent(VCS_EVT_SEND_REQ); // this is your function, remember?
/* Send the raw data to the host via Comm Server */
EESL_send_event("COMMSVR", VCS_EVT_DATA_RAW, buffer, sendLength);
// Read Comm Server's response message. Note that this isn't yet the host response
// message. We're simply checking to make sure that our data was delivered correctly
// to Comm Server. We'll get the actual response later...
ReadEvent(VCS_EVT_SEND_RESP); // your function
5) 接收
vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
/* Add parameters to send to server */
shVarAddUnsignedInt(VCS_FLD_RECV_BUFSIZE, p_size);
shVarAddUnsignedInt(VCS_FLD_RECV_TIMEOUT, p_timeout);
// Send Event to server. Again, note that this doesn't actually receive any data,
// it simply prepares comm server for sending us the raw data and will
// tell us how many bytes we should be expecting
SendEvent(VCS_EVT_RECV_REQ);
// Read event from server
ReadEvent(VCS_EVT_RECV_RESP);
// Extract data from event buffer. We're particularly interested in the number
// total of bytes available to read. Note that we haven't actually read anything
// at this point. We simply got the number of bytes AVAILABLE to read
ushInitStandardFlexi(eco->Buffer);
//Now do the actual read
EESL_send_event("COMMSVR", VCS_EVT_DATA_RAW, (unsigned char *)buffer, readSize);
5) 断开连接
vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
SendEvent(VCS_EVT_DISC_REQ)
ReadEvent(VCS_EVT_DISC_RESP);
它的内容不止于此,但这就是它的要点。
此时,您可能会想,“这看起来很复杂——没有 CommServer 怎么办?” 好吧,现在我们正在冒险进入一个我不太熟悉的领域,我可能不会有那么大的帮助,但我确实有一个代码示例可以进行以下调用(请注意,我的代码示例超过 1500 行,所以我不能在这里全部包括在内):
//important includes:
#include <ctype.h>
#include <svc_net.h>
#include <ceif.h>
#include <vos_ddi_ini.h>
// Init Comm Engine
ceRegister();
// Subscribe to notification events from CommEngine
ceEnableEventNotification();
// Check how many network interfaces (NWIF) are available and store in stNIInfo
g_NICount=ceGetNWIFCount();
g_NIInfo = (unsigned char*) malloc (g_NICount * sizeof (stNIInfo));
ceGetNWIFInfo((stNIInfo*)g_NIInfo, g_NICount, &nwInfoCount);
FillNWIF ((stNIInfo*)g_NIInfo, g_NICount);
// Check the link speed
ceGetDDParamValue (g_currMediaInfo.niHandle, "GET_LINK_SPEED",
sizeof (szLinkSpeed), szLinkSpeed, &linkValueLen);
其中 FillNWIF 定义为
void FillNWIF (stNIInfo stArray[], int arrayCount)
{
int cntr = 0;
for (cntr = 0; cntr < arrayCount; cntr++)
{
if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_ETH) == 0)
g_Devices.devEthernet.iDevHandle = stArray [cntr].niHandle;
else if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_PPPDIAL) == 0)
g_Devices.devDialPPP.iDevHandle = stArray [cntr].niHandle;
else if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_DIALONLY) == 0)
g_Devices.devDial.iDevHandle = stArray [cntr].niHandle;
}
}
简而言之,实际的连接和发送如下:
struct sockaddr_in sockHost;
memset (&sockHost, 0, sizeof (struct sockaddr_in));
memset (&timeout, 0, sizeof (struct timeval));
sockHost.sin_family = AF_INET;
sockHost.sin_addr.s_addr = htonl (inet_addr (g_AppConfig.szHostIP));
sockHost.sin_port = htons (g_AppConfig.iPort);
sockType = SOCK_STREAM;
sockHandle = socket (AF_INET, sockType, 0);
connect (sockHandle, (struct sockaddr*)&sockHost, sizeof (struct sockaddr_in));
send (iSockHandle, szSendBuff, uiSendSize, 0);
recv (iSockHandle, szRecvBuff, sizeof (szRecvBuff), 0);
您可能会觉得有用的其他 API:
//get network interface start mode
ceGetNWIFStartMode (g_currMediaInfo.niHandle);
// Get the total number of network interface from this terminal
g_NICount=ceGetNWIFCount();
//Get network interfaces
ceGetNWIFInfo((stNIInfo*)g_NIInfo, g_NICount, &nwInfoCount);
// only open the NWIF
ceStartNWIF (g_currMediaInfo.niHandle, CE_OPEN);
//close NWIF
ceStopNWIF (g_currMediaInfo.niHandle, CE_CLOSE);
// connect
ceStartNWIF (g_currMediaInfo.niHandle, CE_CONNECT);
//get connection status
ceGetNWParamValue (iNWIFHandle, IP_CONFIG, &ipConfig, sizeof (stNI_IPConfig), &pLen);
//link up
ceStartNWIF (g_currMediaInfo.niHandle, CE_LINK)
//network up
ceStartNWIF (g_currMediaInfo.niHandle, CE_NETWORK);
//network down
ceStopNWIF (g_currMediaInfo.niHandle, CE_NETWORK);
//link down
ceStopNWIF (g_currMediaInfo.niHandle, CE_LINK);
//Disconnect
ceStopNWIF (g_currMediaInfo.niHandle, CE_DISCONNECT);
// Get the version;
ceGetVersion (CE_VER_VXCE, sizeof (g_szVXCEVersion), g_szVXCEVersion);
ceGetVersion (CE_VER_CEIF, sizeof (g_szCEIFVersion), g_szCEIFVersion);
为了解决下面的 make 文件注释,你的 make 文件应该有如下一行:
$(EVOSDK)\bin\vrxcc $(COptions) $(Includes) $(AppObjects) $(Libs) -o $(OutDir)\Project.out`.
在此之上,需要定义COptions
、Includes
、AppObjects
和中的每一个。Libs
选项
COptions
是您要使用的编译器选项。您的“Verix eVo Volume III OS 编程工具参考手册”中有几个可能的选项,但作为示例,您可以将其设置为:
COptions = -p -DLOGSYS_FLAG -DLOGSYS_NEW_API_STYLE
-p
表示它适用于 ARM11 处理器(即,此代码适用于 520,而不是 570)-DLOGSYS_FLAG
表示您要启用 LOG_PRINTF 语句和-DLOGSYS_NEW_API_STYLE
表示您要使用新的宏(不需要双括号)包括
Includes
是告诉编译器在哪里查找头文件 (.h) 的方式。任何时候使用#include
语句时,都需要确保该.h
文件所在的目录出现在Includes
列表中。例如,如果你愿意,#include <ceif.h>
那么你需要确保你有-I$(EOSSDK)\include
作为你的包含路径的一部分。您可以如何设置您的Includes
可能的一个示例是:
Includes = -I.\include -I$(EVOSDK)\include -I$(EOSSDK)\include -I$(EVOACT)\include -I$(EVOVCS)include -I$(EVOVMAC)include
-I
每个前面都有一个。这告诉编译器它是一个Include
而不是库文件。.\include
指向我制作的 .h 文件。请注意,它使用相对目录,因此它假定我的包含文件夹在我的 make 文件存在的同一位置可见。EVOSDK
、EOSSDK
和中的每一个EVOACT
都可能在您的所有项目中使用EVOVCS
是如果您使用的是 commserverEVOVMAC
是如果您使用的是 VMAC(如果您使用的是 commserver,您将是)应用对象
对于您拥有的每个.c
文件,您需要将其编译成一个对象 ( .o
) 文件。您可以在技术上将其汇总到Libs
下面,因为它实际上是同一件事。唯一的区别是你做了这些;它们不是 SDK 或任何东西的一部分。
库
Libs
可能看起来像这样:
Libs = $(EOSSDK)\lib\svc_net.o \
$(EOSSDK)\lib\ssl.o \
$(EOSSDK)\lib\ceif.o \
$(EOSSDK)\lib\elog.o \
$(EVOACT)\Output\RV\Files\Static\Release\act2000.a
ceif.o
是您需要使用 ceif.h 中定义的东西的目标文件。\
每行的末尾都有一个(最后一行除外)。这只是告诉 nmake 这条线还在继续。您可以正确地删除每个\
并将其全部放在 1 行上。这只是为了可读性。最后一部分,-o $(OutDir)\Project.out
只是说你想在哪里输出你的编译结果。