荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: cay (忧郁的年头), 信区: Program
标  题: 将Socket应用程序从Unix向Windows移植中应注意的几点
发信站: 荔园晨风BBS站 (Thu Nov 29 07:43:24 2001), 转信

山东省淄博市建设银行科技部 孙成山

    套接字(socket)当今已成为最流行的网络通信应用程序接口。套接字最初是
由加利福尼亚大学Berkeley分校为Unix操作系统开发的网络通信接口,后来它又被
移植到DOS与Windows系统,特别是近几年来互联网络在全世界范围内被广泛普及并
且增长迅猛,进一步奠定了它在网络通信程序开发领域的主宰地位。跨系统网络互
联的呼声在我国也越来越高。近来,在开发的银行与证券联网系统中,我们尝试做
了由Unix Sockets到Windows Sockets通信应用程序的移植,有所体会,望能将移
植过程中应该注意的几点问题与热心于这方面工作的人们共同作以探讨,以期能起
到抛砖引玉的作用。

修改头文件的定义
在Unix Sockets应用程序中包含头文件的语句为#include<sys/socket.h>,而在
Windows Sockets应用程序中相应语句应为 #include<winsock.h>。

Windows Sockets的实现由两部分组成,即开发组件与运行组件。开发组件是供程
序员开发Windows Sockets 应用程序使用的,它包括Windows Sockets应用程序接
口函数库、头文件以及一些介绍Windows Sockets实现的文档,其中头文件
winsock.h中包含了Windows Sockets 实现所定义的宏、常数值、数据结构和函数
调用接口原型。Winsock.h是编写Windows Sockets应用程序必须包含的头文件。

Windows Sockets DLL初始化与资源释放
在Windows Sockets的接口函数中,提供了WSAStartup()与WSACleanup()两个函数
,用于在程序开始时初始化Windows Sockets DLL和程序结束时释放Windows
Sockets DLL资源,它们是编写Windows Sockets应用程序时必须使用的两个函数。


将套接字的类型由int改为SOCKET
在Unix系统中,套接字类型定义为int型,而在Windows系统中,套接字类型被定义
为SOCKET型,即unsigned int型。

错误码的获取与设置
在Unix系统中,获取、设置错误码使用全局变量errno,而在Windows系统中则应将
其改为用函数WSAGetLastError()和WSASetLastError()。Windows Sockets 为了与
多线程环境兼容,提供了两个出错处理函数WSAGetLastError()与
WSASetLastError()来获取与设置当前线程的最近错误号,而不再使用Unix系统中
的全局变量errno和h_errno。

关闭套接字
在Unix系统中使用close()函数来关闭套接字,而在Windows系统中则用
closesocket()函数。

对套接字的控制
在Unix系统中,使用ioctl()函数和fcntl()函数实现对套接字的控制,而在
Windows系统中则应使用ioctlsocket()函数。

getsockopt()和setsockopt()函数的处理
在Unix Sockets和Windows Sockets中对这两个函数提供的支持不同。在Windows
Sockets中getsockopt()与setsockopt()不支持的Berkeley Sockets选项有:

SO_RCVLOWAT 接受低潮标志

SO_RCVTIMEO 接受超时

SO_SNDLOWAT 发送低潮标志

SO_SNDTIMEO 发送超时

IP_OPTIONS 取得IP头中的选项

TCP_MAXSEG 取得TCP最大尺寸

SO_ACCEPTCONN 套接字正在监听

SO_ERROR 取错误状态并清除

SO_TYPE 套接字类型

使用不支持的选项将返回错误码WSAENOPROTOOPT,它由WSAGetLastError()函数返
回。

由于提供的支持不同,进行移植时若有必要应修改相应的源程序。

使用宏FD_XXX来控制fd_set结构
由于Windows Sockets 某些函数在接口上虽然与Unix Sockets一致,但是它们的内
部实现却不一样,例如,在函数select()的参数中,Unix Sockets实现套接字集合
使用的是位掩码,但在Windows Sockets中却是使用一个SOCKET的数组。虽然套接
字的集合仍由fd_set类型表示,但在Unix Sockets 源文件中直接修改fd_set结构
的代码在Windows Sockets环境下将不能正常工作。因此,在进行移植时应将源程序
中对结构fd_set的直接修改改为通过使用FD_XXX宏来修改。

应在Windows Sockets程序中尽量使用WSA宏
在Windows Sockets的头文件中定义了许多以WSA开头的宏,在程序中使用这些宏,
可以大大地增加程序的可读性。例如:

errno = WSAGetLastError();

if (errno = WSAEWOULDBLOCK) {

……

}

这些宏是Windows Sockets就应用程序实现过程中可能会出现的错误,为便于程序
的读写而专门做出的扩充,它是Windows Sockets应用程序编写人员开发程序时共
同遵循的规范,因此应尽量使用这些宏,以增加程序的可读性。

阻塞调用的处理
Windows是非抢先多任务环境,各任务之间的切换是通过消息驱动的,如果一个应
用程序不能主动放弃其控制权,别的应用程序就不能够执行,这一点与Unix操作系
统有着本质的区别。对于从Unix Sockets环境中移植来的应用程序来说,阻塞问题
必须考虑。

为解决阻塞问题,Windows Sockets特增设了如下几个阻塞处理函数:

WSAIsBlocking() 检测阻塞调用是否正在进行

WSACancelBlockingCall() 取消一个正在进行的阻塞调用

WSASetBlocking() 设置自己的阻塞处理例程

WSAUnhookBlockingHook() 恢复默认的阻塞处理例程

为不影响原来环境中的阻塞处理例程,在安装自己的阻塞处理例程时,应注意保存
返回的先前安装的阻塞处理例程的程序实例指针,并在处理结束后恢复。

尽量将阻塞调用改为基于消息的异步操作


在Windows Sockets网络程序设计中,尽管它允许阻塞操作,但是一个阻塞可能阻
塞整个Windows环境,而在Unix Sockets程序中,套接字的默认操作模式却是阻塞
的。Windows Sockets为了支持Windows消息驱动机制,对网络事件采用了基于消息
的异步存取策略,较好的解决了阻塞问题。为此,建议最好将源程序中的阻塞调用
改为基于消息的异步操作。

Windows Sockets为实现异步存取操作增设了如下的有关函数:

WSAAsyncSelect() 标准Berkeley函数select()的异步版本

WSAAsyncGetXByY() 标准Berkeley函数getXbyY()的异步版本

WSACancelAsyncRequest() 取消函数WSAAsyncGetXByY()执行中的实例

由Unix Sockets应用程序向Windows Sockets的移植是一件比较繁琐的工作,在移
植中除了以上与Sockets具体实现直接相关的几点外,还应注意程序开发环境的的
差异,这时程序上也应作一些相应的调整,例如,在Windows应用程序中有关的一
些指针都应设为FAR类型等,这里就不再一一赘述。


--

        放弃是一件最容易的事

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.168]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店