初始化工作OnInit函数: OnInit函数的主要任务是初始化全局变量串口队列。扫描服务器的串口,如果串口可用,则把此串口进入安全队列。以备客户端请求使用。 内容来自www.paper51.com
copyright paper51.com 图 5初始化工作流程 copyright paper51.com
相关代码: 内容来自www.paper51.com
for(i=1;i<=ComCount;i++) paper51.com { paper51.com sprintf(buf,"\\\\.\\COM%d",i); copyright paper51.com if(com.EPortAvailable==com.CheckPort(buf)) copyright paper51.com ComQueue.Push(i); //串口入队列 copyright paper51.com } 内容来自www.paper51.com 服务工作线程ServiceThread由Run函数实现: copyright paper51.com ServiceThread由函数ServerMain打开,开始完成实际服务任务的工作线程,该线程执行服务的具体任务。该函数绑定服务器地址后监听本地端口等待客户端的连接,当客户端连接上后,创建子线程,由子线程来处理这个连接,函数继续监听本地端口。子线程处理完链接后关闭链接套接字退出。 copyright paper51.com
内容来自论文无忧网 www.paper51.com 图 6 服务工作线程流程 http://www.paper51.com 相关代码: http://www.paper51.com sockaddr_in service; paper51.com service.sin_family=AF_INET; 内容来自www.paper51.com service.sin_addr.s_addr=INADDR_ANY; //ip地址 http://www.paper51.com service.sin_port=htons(2501); //端口号 copyright paper51.com
bind(m_socket,(SOCKADDR*)&service,sizeof(service)); copyright paper51.com
listen(m_socket,20); //监听连接 http://www.paper51.com paper51.com while (m_bIsRunning) { //直到服务停止运行 paper51.com AcceptSocket=SOCKET_ERROR; 内容来自论文无忧网 www.paper51.com while(AcceptSocket==SOCKET_ERROR) copyright paper51.com { 内容来自www.paper51.com AcceptSocket=accept(m_socket,NULL,NULL);//接收连接 copyright paper51.com
} copyright paper51.com //创建子线程处理该连接 内容来自论文无忧网 www.paper51.com CreateThread(NULL,NULL,AnswerThread,(LPVOID)AcceptSocket,0,&TId); http://www.paper51.com
} http://www.paper51.com 服务子线程: http://www.paper51.com 由类的静态成员函数作为线程函数。在线程中,首先判断服务器是否还有剩余串口可分配,也就是判断串口队列中是否为空。若为空,则提示用户服务器串口已使用完毕,请稍后在试,断开同客户端的连接。否则串口队列出队列一个串口,分配给该客户使用,接下来就是打开串口,配置串口参数,开启串口监听线程,等待客户端发送的数据。直到客户端断开连接,串口重新进入队列,等待下次的分配。服务子线程退出。 内容来自论文无忧网 www.paper51.com
内容来自论文无忧网 www.paper51.com 图 7 服务子线程工作流程 copyright paper51.com 相关代码: http://www.paper51.com if(!ComQueue.IsEmpty()) //判断队列是否为空 内容来自www.paper51.com { paper51.com com=ComQueue.Pop(); //出队列 内容来自论文无忧网 www.paper51.com sprintf(buf,"\\\\.\\COM%d",com); paper51.com
//打开串口配置默认通信参数 内容来自www.paper51.com Serial.Open(buf,ClientSocket,1024,1024); 内容来自www.paper51.com Serial.StartListener(); //开启监听线程 内容来自论文无忧网 www.paper51.com while(bytesRecv) //连接是否断开 内容来自论文无忧网 www.paper51.com { http://www.paper51.com while(bytesRecv==SOCKET_ERROR) 内容来自论文无忧网 www.paper51.com { http://www.paper51.com
//接受客户端的数据 内容来自论文无忧网 www.paper51.com bytesRecv=recv(ClientSocket,recvbuf,1024,0); http://www.paper51.com } http://www.paper51.com Serial.Write(recvbuf,&Len); //写串口 内容来自论文无忧网 www.paper51.com } copyright paper51.com Serial.StopListener(); //停止监听子线程 内容来自论文无忧网 www.paper51.com Serial.Close(); //关闭串口 内容来自论文无忧网 www.paper51.com
ComQueue.Push(com); //串口入队列 http://www.paper51.com } 内容来自www.paper51.com Else 内容来自www.paper51.com
{ copyright paper51.com
//发送提示信息到客户端 内容来自www.paper51.com send(ClientSocket,szBuffer,strlen(szBuffer),0); 内容来自www.paper51.com closesocket(ClientSocket);//断开连接 copyright paper51.com } 内容来自www.paper51.com
服务的安装 http://www.paper51.com 要使用服务,首先应进行安装。安装过程使SCM知道有这项服务存在,让SCM把它添加到服务列表中。通过调用函数OpenSCManager,打开一个到服务控制管理器的连接。然后调用函数CreateService在SCM数据库中安装服务。函数CreateService的调用中使用了打开SCM的指针,服务名,识别符以及一族填充其他值的基本参数。服务名是指在scm内部使用的服务的名字,删除服务时指定改名字可删除该服务,识别符是指在“控制面板”的“服务”中表示服务项的识别符。最后关闭服务控制管理器的连接。 copyright paper51.com
paper51.com 图 8 服务安装流程 paper51.com 服务的卸载 内容来自论文无忧网 www.paper51.com 卸载服务时,同样需要先打开一个到服务控制管理器的连接。然后查询该服务当前是否是被停止,若还未停止,则调用函数ControlService尝试停止该服务。这样做有利于卸载服务项:如果服务在删除过程中继续运行,则“控制面板”中”服务“将保留与服务的连接,实际上服务可以继续运行;当有人试图停止该“孤儿”服务时,“服务”可能就会抗议。先停止服务再删除它,就可以避免该问题。服务停止后,调用函数DeleteService删除该服务。 内容来自www.paper51.com
http://www.paper51.com 图 9 服务卸载流程 http://www.paper51.com 4.3 串口通信 paper51.com 串行口在Win32中是作为文件来进行处理的,而不是直接对端口进行操作。在Win32环境下,可以把串口看作由文件系统访问的设备。使用标准的CreateFile()函数打开端口,再使用ReadFile()和WriteFile()函数读写数据,就如同端口只是一个文件对象一样。对于串行通信,Win32提供了相应的文件I/O函数与通信函数,使用这些函数,可以编制出符合不同需要的通信程序。 内容来自www.paper51.com
|