您的位置:首页 > 编程语言 > Java开发

java类加载机制的过程

2013-08-01 17:07 260 查看
WinSock编程流程
1、Winsock库的装入、初始化和释放
所有的Winsock函数都是从WS2_32.DLL库导出的,VC++在默认的情况下并没有连接到该库,如果想使用Winsock API,就必须包含相应的库文档。
#pragma comment(lib,"wsock32.lib")
WSAstartup必须是应用程序首先调用的Winsock函数。它允许应用程序指定所需的Windows Sockets API的版本,获取特定的Winsock实现的详细信息。仅当这个函数成功执行之后,应用程序才能调用其他Winsock API.
int WSAStartup(
WORD wVersionRequested,// 应用程序支持最高的WinSock版本。高字节为次版本号,低字节为主版本号
LPWSADATA lpWSAData// 一个指向WSADATA结构的指针。它用来返回DLL库的详细信息
);
lpWSAData参数用来取得DLL库的详细信息,结构定义如下:
typedef struct WSAData {
WORD wVersion; // 库文件建议应用程序使用的版本
WORD wHighVersion; // 库文件支持的最高版本
char szDescription[WSADESCRIPTION_LEN+1];// 库描述字符串
char szSystemStatus[WSASYS_STATUS_LEN+1];// 系统状态字符串
unsigned short iMaxSockets; // 同时支持的最大套节字的数量
unsigned short iMaxUdpDg; // 2.0版中已废弃的参数
char FAR* lpVendorInfo; // 2.0版中已废弃的参数
} WSADATA, *LPWSADATA;
函数成功调用返回0。否则要调用WSAGetLastError函数查看出错的原因。此函数的作用相当于Win32 API GetLastError,它要取得最后发生错误的代码。
每一个对WSAStartup的调用必须对应一个对WSACleanup的调用,这个函数释放Winsock库。
2、套节字的创建和关闭
使用套节字之前,必须调用socket函数创建一个套节字对象,此函数调用成功将返回套节字句柄。
SOCKET socket(
int af, // 用来指定套节字使用的地址格式,WinSock中只支持AF_INET
int type, // 用来指定套节字的类型
int protocol//配合type参数使用,用来指定使用的协议类型。可以是IPPROTO_TCP等
);
type参数用来指定套节字的类型。套节字有流套节字、数据报套节字和原始套节字等,下面是常见的几种套节字类型的定义:
SOCK_STREAM 流套节字,使用TCP协议提供有连接的可靠的传输
SOCK_DGRAM 数据报套节字,使用UDP协议提供无连接的不可靠的传输
SOCK_RAW 原始套节字,WinSock接口并不使用某种特性的协议去封装他,而是有程序自行处理数据报以及协议首部
当type参数指定为SOCK_STREAM和SOCK_DGRAM时,系统已经明确确定使用TCP和UDP协议来工作,所有protocol参数可以指定为0。
函数执行失败返回INVALID_SOCKET(即-1),应该调用closesocket函数将它关闭。如果没有错误发生,函数返回0,否则返回SOCKET_ERROR。函数用法如下:
int closesocket(
__in SOCKET s // 函数唯一的参数就是要关闭的套节字的句柄
);
3、绑定套节字到指定的IP地址和端口号
为套节字关联本地地址的函数是bing,用法如下:
int bind(
SOCKET s, // 套节字句柄
const struct sockaddr FAR* name, // 要关联的本地地址
int namelen // 地址的长度
);
bind函数用在没有建立连接的套节字上,它的作用是绑定面向连接或者无连接的套节字。当一个套节字被socket函数创建以后,它存在于指定的地址家族里,但是它是未命名的。bind函数通过安排一个本地名称到未命名的socket建立此socket的本地关联。本地名称包含3个部分:主机地址、协议号(分别为UDP何TCP)和端口号。
eg:
// 填充sockaddr_in结构
sockaddr_in① sin;
sin.sin_family = AF_INET;
sin.sin_port = htons②(8888);
sin.sin_addr.S_un.S_addr = INVALIDR_ANY;
// 绑定这个套节字到一个本地地址
if(::bind(s,(LPSOCKADDR)&sin,sizeof(sin)) == SOCKET_ERROR)
{
printf("Failed bind()\n");
::WSACleanup();
return 0;
}
sockaddr_in 结构中的sin_familly字段用来指定地址家族,该字段和socket函数中的af参数的含义相同,所以唯一可以使用的值就是AF_INET。 sin_port字段和sin_addr字段分别指定套节字需要绑定的端口号和IP地址。放入这两个字段的数据的字节顺序必须是网络字节顺序。由于网络字 节顺序和Intel CPU的字节顺序刚好相反,所以必须首先用htons函数进行转换。
如果应用程序不关心 所使用的地址,可以为互联网地址指定INADDR_ANY,为端口号指定0。如果互联网地址等于INADDR_ANY,系统就会自动使用当前主机配置的所 有IP地址,这简化了程序设计;入股端口号等于0,程序执行时系统分配一个唯一的端口号到这个应用程序,其值在1024到5000之前。应用程序可以在 bind之后使用getsockname来知道为它分配的地址。但是要注意,直到套节字连接上之后getsockname函数才能填写互联网地址,因为对 一个主机来说可能有多个地址是可用的。
4、设置套节字进入监听状态
listen函数置套节字进入监听状态。
int listen (
SOCKET s, // 套节字句柄
int backlog, // 监听队列中允许保持的尚未处理的最大连接数量
);
为了接收连接,首先使用socket函数创建一个套节字,然后使用bind函数绑定它到一个本地地址,再用listen函数为到达的连接指定一个backlog,最后使用accept接收请求的连接。
listen仅应用在支持连接的套节字上,如SOCK_STREAM类型。函数返回成功执行之后,套节字s进入了被动模式,到来的连接会被通知,排队等候接受处理。
在同一时间处理多个连接清流的服务器通常使用listen函数:如果一个连接请求到达,并且排队已满,客户端将接收WSAECONNREFUSED错误。
5、接受连接请求
accept函数用于接受到来的连接。
SOCKET accept(
SOCKET s, // 套节字句柄
struct sockaddr *addr, // 一个指向sockaddr_in结构的指针,用于取得对方的地址信息
int* addrlen // 是一个指向地址长度的指针
)
该函数在s上取出未处理连接中的第一个连接,然后为这个连接创建一个新的套节字,返回它的句柄。新创建的套节字是处理实际连接的套节字,它与s有相同的属性。
程序默认工作在阻塞模式下,这种方式下如果没有未处理的连接存在,accept函数会一直等下去直到有新的连接发生才返回。
addrlen参数用于指定addr所指空间的大小,也用于返回地址的实际长度。如果addr或者addrlen是NULL,则没有关于远程地址的信息返回。
客户端程序在创建套节字之后,要使用 connect函数请求与服务器连接,函数原型如下:
int connect(
SOCKET s, // 套节字句柄
const struct sockaddr FAR* name, // 一个指向sockaddr_in结构的指针,包含了要连接的服务器的地址信息
int namelen // sockaddr_in结构的长度
);
第一个参数s是此连接使用的客户端套节字。另两个参数name和namelen用来寻址远程套节字(正在监听的服务器套节字)。
6、收发数据
对流套节字来说,一般使用send和recv函数来收发数据。
int send(
SOCKET s, // 套节字句柄
const char FAR* buf,// 要发送的数据的缓冲区的地址
int len, // 缓冲区的长度
int flags // 指定了的调用方式,通常设为0
);
int recv(
SOCKET s,
char FAR* buf,
int len,
int flags
);
send函数在一个连接的套节字上发送缓冲区内的数据,返回发送数据的实际字节数,recv函数从对方接收数据,并存储它到指定的缓冲区。flag参数在这两个函数中通常设为0。
在阻塞模式下,send将会阻塞线程的执行直到所有的数据发送完毕(或者一个错误的发生),而recv函数将返回尽可能多的当前信息,一直到缓冲区指定的大小。
注解:
①struct sockaddr_in{
shortsin_family; // 地址家族(即指定地址的格式)
unsigned shortsin_port; // 端口号
struct in_addrsin_addr; // IP地址
charsin_zero[8]; //空字节,要设为0
};
②处理本机机器的字节顺序和网络字节顺序的转换:
u_short htons(u_short hostshort); // 转化一个u_short类型从主机字节顺序到TCP/IP网络字节顺序
u_long htonl(u_long hostlong); // 转化一个u_long类型从主机字节顺序到TCP/IP网络字节顺序
u_short ntohs(u_short netlong ); // 转化一个u_short类型从TCP/IP网络字节顺序到主机字节顺序
u_long ntohl(u_long netlong ); // 转化一个u_long类型从TCP/IP网络字节顺序到主机字节顺序
典型过程图

客户方创建套节字后即可调用connect函数去试图连接服务器监听套节字。当服务器方的accept函数返回后,connect函数也返回。此时客户方使用socket函数创建的套节字,服务器方使用accept函数创建的套节字,双方就可以通信了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: