Winsock 应用程式设计(1)

WinCC ActiveX控件设计模式许可证缺失的终极修复指南 本文详细介绍了WinCC ActiveX控件设计模式许可证缺失问题的终极修复方案,包括注册表修复、VB6运行时安装及虚拟机环境特殊处理等。通过注入缺失的许可证密钥和安装必要组件,有效解决"未找到许可证信息"的常见错误,确保WinCC图形编辑器的正常运行。 阅读详情
相信各位读者现在对於 Winsock 的定义、系统环境,以及一些 Winsock Stack及 Winsock 应用程式,都有基本的认识了。接下来笔者希望能分几期为各位读者介绍一下简单的Winsock 网路应用程式设计。

  我们将以 Winsock 1.1 规格所定义的 46 个应用程式介面(API)为基础,逐步来建立一对 TCP socket 主从架构(Client / Server)的程式。在这两个程式中,Server 将使用 Winsock 提供的「非同步」(asynchronous)函式来建立 socket 连结、关闭、及资料收送等等;而 Client 则采类似传统 UNIX 的「阻拦式」(blocking)。由於我们的重点并不在於 MS Windows SDK 的程式设计,所以我们将使用最简便的方式来显示讯息;有关 MS Windows 程式的技巧,请各位读者自行研究相关的书籍及文章。

  今天我们先要看一下主从架构 TCP socket 的建立连结(connect)及关闭(close)。以前笔者曾简单地介绍过主从架构的概念,现在我们再以生活上更浅显的例子来说明一下,读者稍後也较容易能明白笔者的叙述。我们可以假设 Server 就像是电信局所提供的一些服务,比如「104 查号台」或「112 障碍台」。

(1)电信局先建立好了一个电话总机,这就像是呼叫 socket() 函式开启了一个socket。

(2)接著电信局将这个总机的号码定为 104,就如同我们呼叫 bind() 函式,将 Server 的这个 socket 指定(bind)在某一个 port。当然电信局必须让用户知道这个号码;而我们的 Client 程式同样也要知道 Server 所用的 port,待会才有办法与之连接。

(3)电信局的 104 查号台底下会有一些自动服务的分机,但是它的数量是有限的,所以有时你会拨不通这个号码(忙线)。同样地,我们在建立一个 TCP 的Server socket 时,也会呼叫 listen() 函式来监听等待;listen() 的第二个参数即是 waiting queue 的数目,通常数值是由 1 到 5。(事实上这两者还是有点不一样。)

(4)用户知道了电信局的这个 104 查号服务,他就可以利用某个电话来拨号连接这个服务了。这就是我们 Client 程式开启一个相同的 TCP socket,然後呼叫 connect() 函式去连接 Server 指定的那个 port。当然了,和电话一样,如果 waiting queue 满了、与 Server 间线路不通、或是 Server 没提供此项服务时,你的连接就会失败。

(5)电信局查号台的总机接受了这通查询的电话後,它会转到另一个分机做服务,而总机本身则再回到等待的状态。Server 的 listening socket 亦是一样,当你呼叫了 accept() 函式之後,Server 端的系统会建立一个新的 socket 来对此连接做服务,而原先的 socket 则再回到监听等待的状态。

(6)当你查询完毕了,你就可以挂上电话,彼此间也就离线了。Client和Server间的 socket 关闭亦是如此;不过这个关闭离线的动作,可由 Client 端或Server 端任一方先关闭。有些电话查询系统不也是如此吗?

接下来,我们就来看主从架构的 TCP socket 是如何利用这些 Winsock 函式来达成的;并利用资策会资讯技术处的「WinKing」这个 Winsock Stack 中某项功能来显示 sockets 状态的变化。文章中仅列出程式的片段,完整的程式请看附录的程式。

在图 1. 上,我们可以看到最先被呼叫到的是 WSAStartup() 函式。说明下:

WSAStartup():连结应用程式与 Winsock.DLL 的第一个函式。
格式: int PASCAL FAR WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData );
参数: wVersionRequested 欲使用的 Windows Sockets API版本lpWSAData 指向 WSADATA 资料的指标
传回值: 成功 - 0
失败 - WSASYSNOTREADY / WSAVERNOTSUPPORTED / WSAEINVAL
说明: 此函式「必须」是应用程式呼叫到 Windows Sockets DLL 函式中的第一个,也唯有此函式呼叫成功後,才可以再呼叫其他 Windows Sockets DLL 的函式。此函式亦让使用者可以指定要使用的 Windows Sockets API 版本,及获取设计者的一些资讯。

程式中我们要用 Winsock 1.1,所以我们在程式中有一段为:

WSAStartup((WORD)((1<<8)|1),(LPWSADATA) &WSAData)

其中 ((WORD)((1<<8)|1) 表示我们要用的是 Winsock 「1.1」版本,而WSAData 则是用来储存由系统传回的一些有关此一 Winsock Stack 的资料。

再来我们呼叫 socket() 函式来开启 Server 端的 TCP socket。

socket():建立Socket。
格式: SOCKET PASCAL FAR socket( int af, int type, int protocol );
参数: af 目前只提供 PF_INET(AF_INET)
type Socket 的型态 (SOCK_STREAM、SOCK_DGRAM)
protocol 通讯协定(如果使用者不指定则设为0)
传回值: 成功 - Socket 的识别码
失败 - INVALID_SOCKET(呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来建立一 Socket,并为此 Socket 建立其所使用的资源。
Socket 的型态可为 Stream Socket 或 Datagram Socket。

我们要建立的是 TCP socket,所以程式中我们的第二个参数为SOCK_STREAM,我们并将开启的这个 socket 号码记在 listen_sd 这个变数。

listen_sd = socket(PF_INET, SOCK_STREAM, 0)

接下来我们要指定一个位址及 port 给 Server 的这个 socket,这样 Client 才知道待会要连接哪一个位址的哪个 port;所以我们呼叫 bind() 函式。

bind():指定 Socket 的 Local 位址 (Address)。
格式: int PASCAL FAR bind( SOCKET s, const struct sockaddr FAR *name,int namelen );

参数: s Socket的识别码
name Socket的位址值
namelen name的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是指定 Local 位址及 Port 给某一未定名之 Socket。使用者若不在意位址或 Port 的值,那麽他可以设定位址为 INADDR_ANY,及 Port 为 0;那麽Windows Sockets 会自动将其设定适当之位址及 Port (1024 到 5000之间的值),使用者可以在此 Socket 真正连接完成後,呼叫 getsockname() 来获知其被设定的值。bind() 函式要指定位址及 port,这个位址必须是执行这个程式所在机器的 IP位址,所以如果读者在设计程式时可以将位址设定为 INADDR_ANY,这样Winsock 系统会自动将机器正确的位址填入。如果您要让程式只能在某台机器上执行的话,那麽就将位址设定为该台机器的 IP 位址。由於此端是 Server 端,所以我们一定要指定一个 port 号码给这个 socket。

读者必须注意一点,TCP socket 一旦选定了一个位址及 port 後,就无法再呼叫另一次 bind 来任意更改它的位址或 port。

在程式中我们将 Server 端的 port 指定为 7016,位址则由系统来设定。

【Server 端建立 socket 并进入监听等待状态】

首先我们先看 Server 端如何建立一个 TCP socket,并使其进入监听等待的状态。

struct sockaddr_in sa;
sa.sin_family = PF_INET;
sa.sin_port = htons(7016); /* port number */
sa.sin_addr.s_addr = INADDR_ANY; /* address */
bind(listen_sd, (struct sockaddr far *)&sa, sizeof(sa))

  我们在指定 port 号码时会用到 htons() 这个函式,主要是因为各机器的数值读取方式不同(PC 与 UNIX 系统即不相同),所以我们利用这个函式来将 host order 的排列方式转换成 network order 的排列方式;相同地,我们也可以呼叫ntohs() 这个相对的函式将其还原。(host order 各机器不同,但 network order 都相同)(htons 是针对 short 数值,对於 long 数值则用 hotnl 及 ntohl)指定完位址及 port 之後,我们呼叫 listen() 函式,让这个 socket 进入监听状态。一个 Server 端的 TCP socket 必须在做完了 listen 的呼叫後,才能接受 Client 端的连接。

listen():设定 Socket 为监听状态,准备被连接。
格式: int PASCAL FAR listen( SOCKET s, int backlog );
参数: s Socket 的识别码
backlog 未真正完成连接前(尚未呼叫 accept 前)彼端的连接要求的最大个数
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 使用者可利用此函式来设定 Socket 进入监听状态,并设定最多可有多少个在未真正完成连接前的彼端的连接要求。(目前最大值限制为 5, 最小值为1)

程式中我们将 backlog 设为 1 。

listen(listen_sd, 1)

  呼叫完 listen 後,此时 Client 端如果来连接的话,Client 端的连接动作(connect)会成功,不过此时 Server 端必须再呼叫 accept() 函式,才算正式完成 Server 端的连接动作。但是我们什麽时候可以知道 Client 端来连接,而适时地呼叫 accept 呢?在这里我们就要利用一个很好用的 WSAAsyncSelect 函式,将 Server 端的这个 socket 转变成 Asynchronous 模式,让系统主动来通知我们有 Client 要连接了。(图1. 中并未将此函式绘出)

WSAAsyncSelect():要求某一 Socket 有事件 (event) 发生时通知使用者。
格 式: int PASCAL FAR WSAAsyncSelect( SOCKET s, HWND hWnd,unsigned int wMsg, long lEvent );
参 数: s Socket 的编号
hWnd 动作完成後,接受讯息的视窗 handle
wMsg 传回视窗的讯息
lEvent 应用程式有兴趣的网路事件
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是让使用者用来要求 Windows Sockets DLL 在侦测到某一 Socket有网路事件时送讯息到使用者指定的视窗;网路事件是由参数 lEvent 设定。呼叫此函式会主动将该 Socket 设定为 Non-blocking 模式。lEvent 的值可为以下之「OR」组合:(参见 WINSOCK第1.1版88、89页) FD_READ、FD_WRITE、FD_OOB、FD_ACCEPT、FD_CONNECT、FD_CLOSE 使用者若是针对某一Socket再次呼叫此函式时,会取消对该 Socket 原先之设定。若要取消对该Socket 的所有设定,则 lEvent 的值必须设为 0。

(图2) WSAAsyncSelect 函式参数与应用程式关系

  我们在程式中要求 Winsock 系统知道 Client 要来连接时,送一个ASYNC_EVENT 的讯息到程式中 hwnd 这个视窗;由於我们想知道的只有 accept事件,所以我们只设定 FD_ACCEPT。

WSAAsyncSelect(listen_sd, hwnd, ASYNC_EVENT, FD_ACCEPT)

(图 3)demoserv 在 WinKing 系统上建立 socket 并进入监听状态

  读者必须注意一点,WSAAsyncSelect 的设定是针对「某一个 socket」;也就是说,只有当您设定的这个 socket (listen_sd)的那些事件(FD_ACCEPT)发生时,您才会收到这个讯息(ASYNC_EVENT)。如果您开启了很多 sockets,而要让每个 socket 都变成 asynchronous 模式的话,那麽就必须对「每一个 socket」都呼叫 WSAAsyncSelect 来一一设定。而如果您想将某一个 socket 的 async 事件通知设定取消的话,那麽同样也是用 WSAAsyncSelect 这个函式;且第四个参数lEvent 一定要设为 0。

WSAAsyncSelect( s, hWnd, 0, 0 ) -- 取消所有 async 事件设定

  在这里笔者还要告诉各位一点,呼叫 WSAAsyncSelect 的同时也将此一 socket改变成「非阻拦」(non-blocking)模式。但是此时这个 socket 不能很简单地用 ioctlsocket() 这个函式就将它再变回「阻拦」(blocking)模式。也就是说WSAAsyncSelect 和 ioctlsocket 所改变的「非阻拦」模式仍是有些不同的。如果您想将一个「非同步」(asynchronous)模式的 socket 再变回「阻拦」模式的话,必须先呼叫 WSAAsyncSelect() 将所有的 async 事件取消,再用 ioctlsocket() 将它变回阻拦模式。

ioctlsocket():控制 Socket 的模式。
格式: int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR * argP );
参数: s Socket 的识别码
cmd 指令名称
argP 指向 cmd 参数的指标
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取或设定 Socket 的运作参数。其所提供的指令有:(参见 WINSOCK 第 1.1 版 35、36 页)
cmd 的值可为:
FIONBIO -- 开关 non-blocking 模式
FIONREAD -- 自 Socket 一次可读取的资料量(目前 in buffer 的资料量)

SIOCATMARK -- OOB 资料是否已被读取完

  由於我们 Server 端的 socket 是用非同步模式,且设定了 FD_ACCEPT 事件,所以当 Client 端和我们连接时,Winsock Stack 会主动通知我们;我们再先来看看Client 端要如何和 Server 端建立连接?

【Client 端向 Server 端主动建立连接】

  Client 首先也是呼叫 WSAStartup() 函式来与 Winsock Stack 建立关系;然後同样呼叫 socket() 来建立一个 TCP socket。(读者此时一定要用 TCP socket 来连接Server 端的 TCP socket,而不能用 UDP socket 来连接;因为相同协定的 sockets 才能相通,TCP 对 TCP,UDP 对 UDP)和 Server 端的 socket 不同的地方是:Client 端的 socket 可以呼叫 bind()函式,由自己来指定 IP 位址及 port 号码;但是也可以不呼叫 bind(),而由 Winsock Stack来自动设定 IP 位址及 port 号码(此一动作在呼叫 connect() 函式时会由 Winsock 系统来完成)。通常我们是不呼叫 bind(),而由系统设定的,稍後可呼叫getsockname() 函式来检查系统帮我们设定了什麽 IP 及 port。一般言,系统会自动帮我们设定的 port 号码是在 1024 到 5000 之间;而如果读者要自己用 bind 设定 port 的话,最好是 5000 以上的号码。

connect():要求连接某一 TCP Socket 到指定的对方。
格式: int PASCAL FAR connect( SOCKET s, const struct sockaddr FAR *name, int namelen );
参数: s Socket 的识别码
name 此 Socket 想要连接的对方位址
namelen name的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫WSAGetLastError()可得知原因)
说明: 此函式用来向对方要求建立连接。若是指定的对方位址为 0 的话,会传回错误值。当连接建立完成後,使用者即可利用此一 Socket 来做传送或接收资料之用了。

  我们的例子中, Client 是要连接的是自己机器上 Server 所监听的 7016 这个 port,所以我们有以下的程式片段。(假设我们机器的 IP 存在my_host_ip)

struct sockaddr_in sa; /* 变数宣告 */
sa.sin_family = PF_INET; /* 设定所要连接的 Server 端资料 */

sa.sin_port = htons(7016);
sa.sin_addr.s_addr = htonl(my_host_ip);
connect(mysd, (struct sockaddr far *)&sa, sizeof(sa)) /* 建立连接 */

【Server 端接受 Client 端的连接】

  由於我们 Server 端的 socket 是设定为「非同步模式」,且是针对 FD_ACCEPT这个事件,所以当 Client 来连接时,我们 Server 端的 hwnd 这个视窗会收到Winsock Stack 送来的一个 ASYNC_EVENT 的讯息。(参见前面 WSAAsyncSelect 的设定)

  这时,我们应该先利用 WSAGETSELECTERROR(lParam) 来检查是否有错误;并由 WSAGETSELECTEVENT(lParam) 得知是什麽事件发生(因为WSAAsyncSelect 函式可针对同一个 socket 同时设定很多事件,但是只用一个讯息来代表)(此处当然是 FD_ACCEPT 事件);然後再呼叫相关的函式来处理此一事件。所以我们呼叫 accept() 函式来建立 Server 端的连接。

accept():接受某一 Socket 的连接要求,以完成 Stream Socket 的连接。
格式: SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR *addr, int FAR *addrlen );
参数: s Socket的识别码
addr 存放来连接的彼端的位址 addrlen addr的长度
传回值:成功 - 新的Socket识别码
失败 - INVALID_SOCKET (呼叫 WSAGetLastError() 可得知原因)
说明: Server 端之应用程式呼叫此一函式来接受 Client 端要求之 Socket 连接动作;如果Server 端之 Socket 是为 Blocking 模式,且没有人要求连接动作,那麽此一函式会被 Block 住;如果为 Non-Blocking 模式,此函式会马上回覆错误。accept()函式的答覆值为一新的 Socket,此新建之 Socket 不可再用来接受其它的连接要求;但是原先监听之 Socket 仍可接受其他人的连接要求。

  TCP socket 的 Server 端在呼叫 accept() 後,会传回一个新的 socket 号码;而这个新的 socket 号码才是真正与 Client 端相通的 socket。比如说,我们用socket() 建立了一个 TCP socket,而此 socket 的号码(系统给的)为 1,然後我们呼叫的bind()、listen()、accept() 都是针对此一 socket;当我们在呼叫 accept()後,传回值是另一个 socket 号码(也是系统给的),比如说 3;那麽真正与 Client 端连接的是号码 3 这个 socket,我们收送资料也都是要利用 socket 3,而不是 socket 1;读者不可搞错。

  我们在程式中对 accept() 的呼叫如下;我们并可由第二个参数的传回值,得知究竟是哪一个 IP 位址及 port 号码的 Client 与我们 Server 连接。

struct sockaddr_in sa;
int sa_len = sizeof(sa);
my_sd = accept(listen_sd, (struct sockaddr far *)&sa, &sa_len)

  当 Server 端呼叫完 accept() 後,主从架构的 TCP socket 连接才算真正建立完毕;Server 及 Client 端也就可以分别利用此一 socket 来送资料到对方或收对方送来的资料了。(有关资料的收送,我们等下一期再谈)

(图 4) demoserv 与 democlnt 在 WinKing 上连接成功後状态

【Server 及 Client 端结束 socket 连接】

最後我们来看一下如何结束 socket 的连接。socket 的关闭很简单,而且可由Server 或 Client 的任一端先启动,只要呼叫 closesocket() 就可以了。而要关闭监听状态的socket,同样也是利用此一函式。

closesocket():关闭某一Socket。
格式: int PASCAL FAR closesocket( SOCKET s );
参数: s Socket 的识别码
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是用来关闭某一 Socket。若是使用者原先对要关闭之 Socket 设定 SO_DONTLINGER,则在呼叫此一函式後,会马上回覆,但是此一 Sokcet 尚未传送完毕的资料会继续送完後才关闭。若是使用者原先设定此Socket为 SO_LINGER,则有两种情况:
(a) Timeout 设为 0 的话,此一 Socket 马上重新设定 (reset),未传完或未收到的资料全部遗失。
(b) Timeout 不为 0 的话,则会将资料送完,或是等到 Timeout 发生後才真正关闭。

  程式结束前,读者们可千万别忘了要呼叫 WSACleanup() 来通知 Winsock Stack;如果您不呼叫此一函式,Winsock Stack 中有些资源可能仍会被您占用而无法清除释放哟。

WSACleanup():结束 Windows Sockets DLL 的使用。
格式: int PASCAL FAR WSACleanup( void );
参数: 无
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 应用程式在使用 Windows Sockets DLL时必须先呼叫 WSAStartup()来向 Windows Sockets DLL 注册;当应用程式不再需要使用Windows Sockets DLL 时,须呼叫此一函式来注销使用,以便释放其占用的资源。

【结语】

这期笔者先介绍主从架构 TCP sockets 的连接及关闭,以後会再陆续介绍如何收送资料,以及其他 API 的使用。想要进一步了解如何撰写 Winsock 程式的读者,可以好好研究一下笔者 demoserv 及 democlnt 这两个程式;也许不是写的很好,但是希望可以带给不懂 Winsock 程式设计的人一个起步。读者们亦可自行用 anonymous ftp 方式到 SEEDNET 台北主机 tpts1.seed.net.tw(139.175.1.10)的 UPLOAD / WINKING 目录下,取得笔者与陈建伶小姐所设计的WinKing 这个 Winsock Stack 的试用版,来跑 demoserv 与democlnt 这两个程式及其他许许多多的 Winsock 应用程式。(正式版本请洽 SEEDNET 服务中心,新版的WinKing 已含 Windows 拨接及 PPP 程式,适合电话拨接用户在Windows 环境下使用 SEEDNET;WinKing 同样也提供 Ethernet 环境的使用。)

用WINSOCK实现聊天室的VC++程序设计 用WINSOCK实现聊天室的VC++程序设计 一、SOCKET简介 80年代初,美国政府的高级研究工程机构(ARPA)给加利福尼亚大 学Berkeley分校提供了资金,让他们在UNIX操作系统下实现TCP/IP协 议。在这个项目中,研究人员为TCP/IP网络通信开发了一个API(应用 程序接口)。这个API称为Socket接口(套接字)。今天,SOCKET接口 是TCP/IP网络最为通用的API, 阅读详情

相关推荐

解决vb6加载winsock提示“该部件的许可证信息没有找到。在设计环境中,没有合适的许可证使用该功能”的方法

vb6加载winsock控件是提示:该部件的许可证信息没有找到。在设计环境中,没有合适的许可证使用该功能,不能添加控件,下载注册表文件,加载即可。

CentOs 安装主意事项

安装注意事项 1 关于分区的问题,我们分四个分区(建议这四个分区不要占满,原因为了扩展,添加新的东西,不用挂在这四个分区以下,避免影响) 比如20G / 10G /home 2G /boot 500M swap

无风子 436

计算机网络设计二:Winsock及其应用设计

有具体的步骤,并附有截图,一目了然,适合广大初学者。

【亲测免费】 解决VB6加载Winsock控件许可证问题的注册表文件

解决VB6加载Winsock控件许可证问题的注册表文件 【下载地址】解决VB6加载Winsock控件许可证问题的注册表文件 在使用VB6开发环境时,有时会遇到加载Winsock控件时提示“该部件的许可证信息没有找到。在设计环境中,没有合适的许可证使用该功能”的问题。这个问题会导致无法正常添加Winsock控件到你的项目中...

gitblog_09794的博客 482

AAA 源代码:基于WinScok的聊天软件的设计与实现 C++

搜索括号里的关键词获得更多的资源: (AAA 计算机相关英文翻译:WinSock 聊天软件 C++) (AAA 文献综述: WinSock 聊天软件 C++ ) (AAA 源代码:基于WinScok的聊天软件的设计与实现 C++) (AAA 毕业论文:基于WinSock的聊天软件的设计与实现 C++)

R语言灰色关联分析法

输入数据并用DT包的datatable函数展示数据 ABDDEF分别对应第1到第6个供应商产品质量、技术水平、供应能力、经济效益、交货情况、市场影响度指标属于效益型指 产品价格、地理位置、售后服务指标属于成本型指标。现分别对上述指标进行规范化: 对于效益型指标(正项指标)标准化公式为: x∗=x−min(x)max(x)−min(x) x^{\ast}=\frac{x-min\left( x \right)}{max\left( x \right) -min\left( x \right)} x∗=max

qq_54423921的博客 7996

WinCC 使用ActiveX控件,提示:“未找到许可证信息,没有设计模式的有效许可证”解决办法

在WinCC 画面绘制过程中,使用Microsoft Date and Time Picker Control 6.0(SP4)控件时提示,未找到许可证。4.弹出如下图所示对话框,完成注册表写入。再次打开WINCC,即可正常添加控件了。2.将文末代码复制到记事本中,并另存为VBCTRLS.reg文件,如下图所示。我自己使用的是WINCC 7.5 SP2,亲测有效,其他版本大家也可试试。3.双击VBCTRLS文件,弹出下图所示对话框,点击“是”。1.首先取消激活并关闭WINCC软件。

qq_44894693的博客 6461

别再为域名备案发愁了!微信小程序后端调用,试试这个‘官方捷径’——云托管

本文介绍了微信小程序后端部署的新思路——利用微信云托管服务绕过域名备案难题。通过详细的环境准备、数据库配置、服务部署和小程序端调用方案,帮助开发者快速实现小程序与后端服务的无缝对接,大幅缩短上线周期并降低运维成本。

weixin_29243279的博客 674

简单的 Winsock 应用程式设计(1)

简单的 Winsock 应用程式设计(1) 林 军 鼐 相信各位读者现在对於 Winsock 的定义、系统环境,以及一些 Winsock Stack 及 Winsock 应用程式,都有基本的认识了。接下来笔者希望能分几期为各位读者 介绍一下简单的 Winsock 网路应用程式设计。 我们将以 Winsock 1.1 规格所定义的 46 个应用程式介面(API)为基础,逐 步来建立一对 TCP so

堯仸的专栏 1266

无人机频谱侦测与智能识别技术实战解析

本文深入解析无人机频谱侦测与智能识别技术实战应用,涵盖无线电侦测、信号处理和定位技术等核心内容。通过频谱分析、特征提取和机器学习算法优化,实现高精度无人机识别与定位,并分享复杂环境下的应对策略和系统集成经验。

weixin_28419039的博客 488

从零上手:基于英飞凌TC377的UDE STK 5.0实战调试指南

本文详细介绍了基于英飞凌TC377芯片和UDE STK 5.0的实战调试指南,涵盖硬件连接、工作空间配置、程序烧录、多核调试等关键步骤。特别针对汽车电子领域常见的多核架构调试难题,提供了断点设置、变量监控等实用技巧,帮助开发者快速上手并优化调试效率。

weixin_30839881的博客 683

简单的 Winsock 应用程式设计

简单的 Winsock 应用程式设计(1) 林 军 鼐 相信各位读者现在对於 Winsock 的定义、系统环境,以及一些 Winsock Stack 及 Winsock 应用程式,都有基本的认识了。接下来笔者希望能分几期为各位读者介绍一下简单的 Winsock 网路应用程式设计。我们将以 Winsock 1.1 规格所定义的 46 个应用程式介面(API)为基础,逐步来建立一对 T

my15y的专栏 1367

联想ThinkPad声卡驱动安装避坑指南:从E470到X1 Carbon的通用解法

本文详细介绍了ThinkPad声卡驱动安装的全流程,从硬件识别到驱动获取、安装技巧及深度排错。涵盖E470到X1 Carbon等不同机型的通用解法,帮助用户解决音频驱动问题,提升使用体验。重点讲解了声音驱动的精准识别和安装策略,确保系统稳定运行。

weixin_29207439的博客 708

简单的 Winsock 应用程式设计(4)

林 军 鼐 笔者在前几期的文章中已经介绍了大部份 Winsock 1.1 所提供的应用程式发 展介面;笔者也相信有读者已经开始利用这些 API 来开发自己的网路应用程式 了。但是可能仍有部份读者还是不清楚自己该先有哪些发展工具才能开发 Winsock 1.1 的应用程式? 基本上,读者当然一定要有 Microsoft C 或 Borland C 之类的编译程式 (Compiler)才能编译您的程式

堯仸的专栏 1299

鸿蒙手机卸载内置应用 adb连接

**傻瓜式删除鸿蒙系统内置应用,自己亲测有效。**

JJDXBT的博客 3万+

域控制器开发避坑实录:从硬件设计到软件集成的5个关键挑战

本文深入剖析了域控制器开发中的5大关键挑战,从硬件选型到软件集成,涵盖智能驾驶芯片选择、实时性优化、AUTOSAR架构适配等核心问题。通过实战案例和数据对比,为工程师提供避坑指南,助力提升开发效率和系统可靠性。

weixin_29258297的博客 395

简单的 Winsock 应用程式设计(2)

林 军 鼐 在前一期的文章中,笔者为大家介绍了如何在 Winsock 环境下,建立主从 架构(Client/Server)的 TCP socket 的连接建立与关闭;今天笔者将继续为大家 介绍如何利用 TCP socket 来收送资料,并详细解说 WSAAsyncSelect 函式中的 FD_READ 及 FD_WRITE 事件(笔者曾发现有相当多人对这两个事件甚不了 解)。 相信读者们已经知道

堯仸的专栏 1151

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Winsock 应用程式设计

 --简单的 Winsock 应用程式设计TCP连接建立与关闭相信各位读者现在对於 Winsock 的定义、系统环境,以及一些 Winsock Stack及 Winsock 应用程式,都有基本的认识了。接下来笔者希望能分几期为各位读者介绍一下简单的 Winsock 网路应用程式设计。我们将以 Winsock 1.1 规格所定义的 46 个应用程式介面(API)为基础,逐步来建立一对 T

MmstZCC(安然)的专栏 653

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

[转帖] 简单的 Winsock 应用程序设计(1)

**********************************************************************Copyright by 林军鼐文稿内容不得转载于任何商业书刊或做任何商业用途**********************************************************************        简单的 Winsock 应

ncdawen的专栏 1612

Winsock程序设计初步之<一> Winsock编程原理

      本课程主要讲Windows中TCP/IP编程接口Winsock,版本为1.1。高版本的Winsock实际与1.1版相差不多,主要是进行了一些扩充,如可超越TCP/IP协议直接用socket来实现IPX、NETBIOS等其它通信协议。这叙述方便在本文的其余部分中提到的Winsock指的就是Winsock1.1。通过Winsock可实现点对点或广播通信程序,实际这两者之间的区别不大

cnviolet的专栏 1474
上一篇: VC++最常见的20种编译错误信息
下一篇: 我有个问题
delphi_dcs
博客等级 码龄22年 3粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值