【问题标题】:Sending data via Ethernet port (verifone vx520)通过以太网端口发送数据(verifone vx520)
【发布时间】:2015-08-13 05:58:07
【问题描述】:

我想使用以太网端口通过创建套接字发送数据。

如何打开以太网端口并设置IP、NETMASK 和GateWay? 我可以使用这些功能,但是我不知道如何打开以太网端口或如何配置这些功能。

ceSETNWParamValue();
ceGetNWParamValue();
ceSetDDParamValue();

【问题讨论】:

    标签: point-of-sale verifone


    【解决方案1】:

    嗯,“Verix eVo 第二卷操作系统和通信程序员指南”(尤其是第 5 章)可以帮助您一点,但在我们开始之前,有一件重要的事情需要考虑 - 如果您正在使用您在 vx520 上编写的这个程序,将来您可能会希望它在另一种终端类型上使用。为此,您可以考虑使用 CommServer。 CommServer 是一个帮助从代码中抽象出各种类型的硬件的程序,因此您可以将相同的命令发送到任何终端类型,并让它根据所使用的硬件确定如何满足您的请求。它已经存在了一段时间,并已移植到大多数 VerFone 终端类型。它由 VeriFone 免费提供(和支持)。它有一些缺点:

    • 它只是增加了 1 个你必须下载的程序(而且它很大)
    • 它要求您通过 Flexi Records 发送请求,起初设置起来可能会有些混乱。
    • 它增加了一层可能使调试复杂化的活动部件
    • 如果您之前没有使用过 VMAC,现在需要使用它(这是另一个程序,而且更复杂)

    但是,一旦你开始工作,它真的很棒:

    • 对所有硬件使用相同的代码
    • 如果终端上运行的多个应用程序都需要使用 IP 通信,则您不需要任何应用程序中的 TCP/IP 库,这通常会导致整体尺寸更小。

    很有可能在某个时候,您需要与另一个第 3 方共享您的终端。如果是这样的话,无论如何,你需要让你的程序在 VMAC 之上运行,而且他们很有可能也会使用 CommServer。如果是这种情况,那么 2 个“CON”就消失了,而一个“PRO”只是被强调了。

    所以现在你必须选择——CommServer,或者没有 CommServer。

    如果您选择 CommServer,您需要非常熟悉 FlexiRecords 的工作原理,因此作为先决条件,我建议您阅读“Verix eVo 多应用程序指挥程序员指南”的第 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 文件 cmets,你的 make 文件应该有如下一行:

    $(EVOSDK)\bin\vrxcc $(COptions) $(Includes) $(AppObjects) $(Libs) -o $(OutDir)\Project.out`. 
    

    在此之上,COptionsIncludesAppObjectsLibs 中的每一个都需要定义。

    COptions

    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 &lt;ceif.h&gt;,那么您需要确保将-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 文件。请注意,它使用相对目录,因此它假定我的 include 文件夹在我的 make 文件所在的同一位置可见。
    • EVOSDKEOSSDKEVOACT 中的每一个都可能用于您的所有项目中
    • EVOVCS 如果您使用的是通讯服务器
    • EVOVMAC 是如果您使用的是 VMAC(如果您使用的是 commserver)
    • 如果您不使用 VMAC 或 CommServer,请关闭最后 2 个。

    应用对象

    对于您拥有的每个 .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 只是说你想在哪里输出你的编译结果。

    【讨论】:

    • 当我包含 &lt;svc_net.h&gt;&lt;ceif.h&gt;&lt;vos_ddi_ini.h&gt; 并编译我的代码时,使用此库会发生错误。我怎样才能添加这个库? (我使用这个命令编译我的代码:vrxcc -p test.c 并且错误是无法打开源输入文件“ceif.h”:没有这样的文件或目录)
    • 感谢您的多次帮助,我可以提供您的电子邮件地址,您想将我的电子邮件发送给您以获取更多详细信息吗...?
    • 如何在我的程序中添加 ceif.h 库?我在我的程序中包含 但它发生错误。
    • 正确 -- 它应该在 %eossdk%\include 中。然后确保您将其包含在您的 make 文件中 --> -I$(EOSSDK)\include 另外,请检查反斜杠“\”是否应该存在(有时它被添加到环境变量中,有时它不是)。还是行不通?错误是什么?
    • 我们正在冒险进入“新问题”领域,但是... VeriFone 项目通常使用“NMAKE”构建。这个工具本质上是一个运行所有构建步骤的脚本,但它需要一个“make 文件”来告诉它这些步骤是什么。 make 文件通常具有扩展名 .smk(至少在 VeriFone 项目中,无论如何)。请注意,从技术上讲,您不需要 make 文件——您可以在命令提示符下完成所有操作。无论您采用哪种方式,您都需要确保将编译器/链接器指向您想要包含的库。所以当你做vrxcc时,你需要-I @farshid
    猜你喜欢
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    相关资源
    最近更新 更多