54.4 emWin VNC接口函数 针对emWinVNC服务器的实现,emWin专门提供了一个接口文件:GUI_VNC_X_StartServer.c,用户在这个文件里面实现VNC的具体功能即可。STemWin软件包中没有此文件,大家可以在MDK安装目录里面找。 1、以MDK4.74为例,是在路径:C:\Keil_v474\ARM\Segger\emWin\Sample\GUI_X。 2、以MDK5.24a为例,是在路径:C:\Keil_v524a\ARM\PACK\Keil\MDK-Middleware\7.4.1\emWin\Sample\GUI_X 对于这个文件,原始内容是基于SEEGGER的embOS实现的: - <font size="3">#include <stdlib.h></font>
-
- #include "IP.h" // BSD socket interface
- #include "RTOS.H" // embOS header
- #include "GUI.h"
- #include "GUI_VNC.h"
-
- /*********************************************************************
- *
- * Static data
- *
- **********************************************************************
- */
- static GUI_VNC_CONTEXT _Context;
- static struct sockaddr_in _Addr;
-
- //
- // embOS Stack area of the server
- //
- static OS_STACKPTR int _StackVNCServer[1000];
-
- //
- // embOS Task-control-block of the server
- //
- static OS_TASK _VNCServer_TCB;
-
- /*********************************************************************
- *
- * Static functions
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * _Send
- *
- * Function description
- * This function is called indirectly by the server; it's address is passed to the actual
- * server code as function pointer. It is needed because the server is independent
- * of the TCP/IP stack implementation, so details for the TCP/IP stack can be placed here.
- */
- static int _Send(const U8 * buf, int len, void * pConnectionInfo) {
- int r;
-
- r = send((long)pConnectionInfo, (const char *)buf, len, 0);
- return r;
- }
-
- /*********************************************************************
- *
- * _Recv
- *
- * Function description
- * This function is called indirectly by the server; it's address is passed to the actual
- * server code as function pointer. It is needed because the server is independent
- * of the TCP/IP stack implementation, so details for the TCP/IP stack can be placed here.
- */
- static int _Recv(U8 * buf, int len, void * pConnectionInfo) {
- return recv((long)pConnectionInfo, (char *)buf, len, 0);
- }
-
- /*********************************************************************
- *
- * _ListenAtTcpAddr
- *
- * Starts listening at the given TCP port.
- */
- static int _ListenAtTcpAddr(U16 Port) {
- int sock;
- struct sockaddr_in addr;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(Port);
- addr.sin_addr.s_addr = INADDR_ANY;
- bind(sock, (struct sockaddr *)&addr, sizeof(addr));
- listen(sock, 1);
- return sock;
- }
-
- /*********************************************************************
- *
- * _ServerTask
- *
- * Function description
- * This routine is the actual server task.
- * It executes some one-time init code, then runs in an ednless loop.
- * It therefor does not terminate.
- * In the endless loop it
- * - Waits for a conection from a client
- * - Runs the server code
- * - Closes the connection
- */
- static void _ServerTask(void) {
- int s, Sock, AddrLen;
- U16 Port;
-
- //
- // Prepare socket (one time setup)
- //
- Port = 5900 + _Context.ServerIndex; // Default port for VNC is is 590x, where x is the 0-based layer index
- //
- // Loop until we get a socket into listening state
- //
- do {
- s = _ListenAtTcpAddr(Port);
- if (s != -1) {
- break;
- }
- OS_Delay(100); // Try again
- } while (1);
- //
- // Loop once per client and create a thread for the actual server
- //
- while (1) {
- //
- // Wait for an incoming connection
- //
- AddrLen = sizeof(_Addr);
- if ((Sock = accept(s, (struct sockaddr*)&_Addr, &AddrLen)) == SOCKET_ERROR) {
- continue; // Error
- }
- //
- // Run the actual server
- //
- GUI_VNC_Process(&_Context, _Send, _Recv, (void *)Sock);
- //
- // Close the connection
- //
- closesocket(Sock);
- memset(&_Addr, 0, sizeof(struct sockaddr_in));
- }
- }
-
- /*********************************************************************
- *
- * Public code
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * GUI_VNC_X_StartServer
- *
- * Function description
- * To start the server, the following steps are executed
- * - Make sure the TCP-IP stack is up and running
- * - Init the server context and attach it to the layer
- * - Start the thread (task) which runs the VNC server
- * Notes:
- * (1) The first part of the code initializes the TCP/IP stack. In a typical
- * application, this is not required, since the stack should have already been
- * initialized some other place.
- * This could be done in a different module. (TCPIP_AssertInit() ?)
- */
- int GUI_VNC_X_StartServer(int LayerIndex, int ServerIndex) {
- //
- // Init VNC context and attach to layer (so context is updated if the display-layer-contents change
- //
- GUI_VNC_AttachToLayer(&_Context, LayerIndex);
- _Context.ServerIndex = ServerIndex;
- //
- // Create task for VNC Server
- //
- OS_CREATETASK(&_VNCServer_TCB, "VNC Server", _ServerTask, 230, _StackVNCServer);
- //
- // O.k., server has been started
- //
- return 0;
- }
-
- /*********************************************************************
- *
- * GUI_VNC_X_StartServerFT
- *
- * Function description
- * In addition to GUI_VNC_X_StartServer() it enables the RFB-protocoll extensions
- * and sets an API-structure containing function pointers required for file access.
- */
- int GUI_VNC_X_StartServerFT(int LayerIndex, int ServerIndex) {
- //
- // Enable file transfer extensions in RFB-protocoll
- //
- GUI_VNC_EnableFileTransfer(1);
- //
- // Set API-functions used for file access
- //
- GUI_VNC_SetFS_API(&IP_FS_FS);
- //
- // Call GUI_VNC_X_StartServer()
- //
- return GUI_VNC_X_StartServer(LayerIndex, ServerIndex);
- }
-
- /*********************************************************************
- *
- * GUI_VNC_X_getpeername
- *
- * Function description
- * Retrieves the IP addr. of the currently connected VNC client.
- *
- * Return values
- * IP addr. if VNC client connected
- * 0 if no client connected
- */
- void GUI_VNC_X_getpeername(U32 * Addr) {
- *Addr = _Addr.sin_addr.s_addr;
- }
-
- /*************************** End of file ****************************
复制代码 如果大家要将此文件在其它RTOS下实现,仅需要修改上面代码中置红的部分即可,主要是创建一个VNC服务器任务。而网络通信的代码是采用的bsd socket,如果大家使用的网络协议栈支持bsd socket,这部分代码是不需要做任何修改的。我们使用的RL-TCPnet网络协议栈是支持bsd scoket的,所以这部分代码无需做修改。 下面的代码是采用RTX操作系统实现的,代码中置红的部分是修改后的。uCOS-III和FreeRTOS也都有实现,参看本章节配套的例子即可: - #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #include "rtl.h"
- #include "GUI.h"
- #include "GUI_VNC.h"
-
- /*********************************************************************
- *
- * Static data
- *
- **********************************************************************
- */
- static GUI_VNC_CONTEXT _Context;
- static struct sockaddr_in _Addr;
-
- static U64 AppTaskVNCStk[4096/8]; /* 任务栈 */
-
-
- /*********************************************************************
- *
- * Static functions
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * _Send
- *
- * Function description
- * This function is called indirectly by the server; it's address is passed to the actual
- * server code as function pointer. It is needed because the server is independent
- * of the TCP/IP stack implementation, so details for the TCP/IP stack can be placed here.
- */
- static int _Send(const U8 * buf, int len, void * pConnectionInfo) {
- int r;
-
- r = send((long)pConnectionInfo, (const char *)buf, len, 0);
- return r;
- }
-
- /*********************************************************************
- *
- * _Recv
- *
- * Function description
- * This function is called indirectly by the server; it's address is passed to the actual
- * server code as function pointer. It is needed because the server is independent
- * of the TCP/IP stack implementation, so details for the TCP/IP stack can be placed here.
- */
- static int _Recv(U8 * buf, int len, void * pConnectionInfo) {
- return recv((long)pConnectionInfo, (char *)buf, len, 0);
- }
-
- /*********************************************************************
- *
- * _ListenAtTcpAddr
- *
- * Starts listening at the given TCP port.
- */
- static int _ListenAtTcpAddr(U16 Port) {
- int sock;
- struct sockaddr_in addr = {0};
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(Port);
- addr.sin_addr.s_addr = INADDR_ANY;
- bind(sock, (struct sockaddr *)&addr, sizeof(addr));
- listen(sock, 1);
- return sock;
- }
-
- /*********************************************************************
- *
- * _ServerTask
- *
- * Function description
- * This routine is the actual server task.
- * It executes some one-time init code, then runs in an ednless loop.
- * It therefor does not terminate.
- * In the endless loop it
- * - Waits for a conection from a client
- * - Runs the server code
- * - Closes the connection
- */
- __task void _ServerTask(void) {
- int s, Sock, AddrLen;
- U16 Port;
- //
- // Prepare socket (one time setup)
- //
- Port = 5900 + _Context.ServerIndex; // Default port for VNC is is 590x, where x is the 0-based layer index
- //
- // Loop until we get a socket into listening state
- //
- do {
- s = _ListenAtTcpAddr(Port);
- if (s != -1) {
- break;
- }
- os_dly_wait(100); // Try again
- } while (1);
- //
- // Loop once per client and create a thread for the actual server
- //
- while (1) {
- //
- // Wait for an incoming connection
- //
- AddrLen = sizeof(_Addr);
- if ((Sock = accept(s, (struct sockaddr*)&_Addr, &AddrLen)) < 0) {
- continue; // Error
- }
- //
- // Run the actual server
- //
- GUI_VNC_Process(&_Context, _Send, _Recv, (void *)Sock);
- //
- // Close the connection
- //
- closesocket(Sock);
- memset(&_Addr, 0, sizeof(struct sockaddr_in));
- }
- }
-
- /*********************************************************************
- *
- * Public code
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * GUI_VNC_X_StartServer
- *
- * Function description
- * To start the server, the following steps are executed
- * - Make sure the TCP-IP stack is up and running
- * - Init the server context and attach it to the layer
- * - Start the thread (task) which runs the VNC server
- * Notes:
- * (1) The first part of the code initializes the TCP/IP stack. In a typical
- * application, this is not required, since the stack should have already been
- * initialized some other place.
- * This could be done in a different module. (TCPIP_AssertInit() ?)
- */
- int GUI_VNC_X_StartServer(int LayerIndex, int ServerIndex) {
- //
- // Init VNC context and attach to layer (so context is updated if the display-layer-contents change
- //
- GUI_VNC_AttachToLayer(&_Context, LayerIndex);
- _Context.ServerIndex = ServerIndex;
-
- //
- // Create task for VNC Server
- //
- os_tsk_create_user(_ServerTask, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskVNCStk, /* 任务栈 */
- sizeof(AppTaskVNCStk)); /* 任务栈大小,单位字节数 */
- //
- // O.k., server has been started
- //
- return 0;
- }
-
- /*********************************************************************
- *
- * GUI_VNC_X_getpeername
- *
- * Function description
- * Retrieves the IP addr. of the currently connected VNC client.
- *
- * Return values
- * IP addr. if VNC client connected
- * 0 if no client connected
- */
- void GUI_VNC_X_getpeername(U32 * Addr) {
- *Addr = _Addr.sin_addr.s_addr;
- }
-
- /*************************** End of file ****************************/
复制代码从上面的代码可以看出,主要是创建一个VNC服务器任务并提供一个延迟函数即可。
|