??xml version="1.0" encoding="utf-8" standalone="yes"?>精品久久久久久无码专区不卡 ,久久久久国产精品嫩草影院,久久久久国产一区二区三区http://www.shnenglu.com/mmdengwo/category/16586.htmlzh-cnThu, 19 May 2011 23:53:33 GMTThu, 19 May 2011 23:53:33 GMT60包和拆?http://www.shnenglu.com/mmdengwo/archive/2011/05/13/146310.html沛沛沛沛Fri, 13 May 2011 05:26:00 GMThttp://www.shnenglu.com/mmdengwo/archive/2011/05/13/146310.htmlhttp://www.shnenglu.com/mmdengwo/comments/146310.htmlhttp://www.shnenglu.com/mmdengwo/archive/2011/05/13/146310.html#Feedback1http://www.shnenglu.com/mmdengwo/comments/commentRss/146310.htmlhttp://www.shnenglu.com/mmdengwo/services/trackbacks/146310.html阅读全文

沛沛 2011-05-13 13:26 发表评论
]]>
WinSock学习W记 http://www.shnenglu.com/mmdengwo/archive/2011/05/03/145571.html沛沛沛沛Tue, 03 May 2011 07:44:00 GMThttp://www.shnenglu.com/mmdengwo/archive/2011/05/03/145571.htmlhttp://www.shnenglu.com/mmdengwo/comments/145571.htmlhttp://www.shnenglu.com/mmdengwo/archive/2011/05/03/145571.html#Feedback0http://www.shnenglu.com/mmdengwo/comments/commentRss/145571.htmlhttp://www.shnenglu.com/mmdengwo/services/trackbacks/145571.html int WSAGetLastError(void ); #define h_errno WSAGetLastError() 错误D自己阅读Winsock2.h?br>
2、将L的unsigned longD{换ؓ|络字节序(32?Qؓ什么要q样做呢Q因Z同的计算Z用不同的字节序存储数据。因此Q何从Winsock函数对IP地址和端口号的引用和传给Winsock函数的IP地址和端口号均时按照|络序l织的?br>
      u_long  htonl(u_long hostlong);
举例Qhtonl(0)=0
htonl(80)= 1342177280
3、将unsigned longC|络字节序转换位主机字节顺序,是上面函数的逆函数?
      u_long  ntohl(u_long netlong);
举例Qntohl(0)=0
ntohl(1342177280)= 80
4、将L的unsigned shortD{换ؓ|络字节序(16?Q原因同2Q?
      u_short  htons(u_short hostshort);
举例Qhtonl(0)=0
htonl(80)= 20480
5、将unsigned shortC|络字节序转换位主机字节顺序,是上面函数的逆函数?
      u_short  ntohs(u_short netshort);
举例Qntohs(0)=0
ntohsl(20480)= 80
6、将用点分割的IP地址转换位一个in_addrl构的地址Q这个结构的定义见笔?一)Q实际上是一个unsigned long倹{计机内部处理IP地址可是不认识如192.1.8.84之类的数据?
      unsigned long  inet_addr( const char FAR * cp );
举例Qinet_addr("192.1.8.84")=1409810880
inet_addr("127.0.0.1")= 16777343
如果发生错误Q函数返回INADDR_NONE倹{?br>
7、将|络地址转换位用点分割的IP地址Q是上面函数的逆函数?
      char FAR *  inet_ntoa( struct in_addr in );
举例Qchar * ipaddr=NULL;
char addr[20];
in_addr inaddr;
inaddr. s_addr=16777343;
ipaddr= inet_ntoa(inaddr);
strcpy(addr,ipaddr); 
q样addr的值就变ؓ127.0.0.1?br>注意意不要修改返回值或者进行释攑֊作。如果函数失败就会返回NULL倹{?br>
8、获取套接字的本地地址l构Q?
      int  getsockname(SOCKET s, struct sockaddr FAR * name, int FAR * namelen );
s为套接字
name为函数调用后获得的地址?
namelen为缓冲区的大?
9、获取与套接字相q的端地址l构Q?br>
      int  getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen );
s为套接字
name为函数调用后获得的端地址?
namelen为缓冲区的大?
10、获取计机名:
      int  gethostname( char FAR * name, int namelen );
name是存放计机名的~冲?
namelen是缓冲区的大?
用法Q?
char szName[255];
memset(szName,0,255);
if(gethostname(szName,255)==SOCKET_ERROR)
{
//错误处理
}
q回gؓQszNmae="xiaojin"
11、根据计机名获取主机地址Q?
      struct hostent FAR *  gethostbyname( const char FAR * name );
name机名?
用法Q?
hostent * host;
char* ip;
host= gethostbyname("xiaojin");
if(host->h_addr_list[0])
{
struct in_addr addr;
memmove(&addr, host->h_addr_list[0]Q?);
//获得标准IP地址
ip=inet_ ntoa (addr);
}
q回gؓQhostent->h_name="xiaojin"
hostent->h_addrtype=2    //AF_INET
hostent->length=4
ip="127.0.0.1"
Winsock 的I/O操作Q?/strong>

1?两种I/O模式
  • d模式Q执行I/O操作完成前会一直进行等待,不会控制权交给E序。套接字 默认为阻塞模式。可以通过多线E技术进行处理?
  • 非阻塞模式:执行I/O操作ӞWinsock函数会返回ƈ交出控制权。这U模式?h比较复杂Q因为函数在没有q行完成p行返回,会不断地q回 WSAEWOULDBLOCK错误。但功能强大?
Z解决q个问题Q提Zq行I/O操作的一些I/O模型,下面介绍最常见的三U:

2、select模型Q?br>
  通过调用select函数可以定一个或多个套接字的状态,判断套接字上是否有数据,?br>者能否向一个套接字写入数据?
      int  select( int nfds, fd_set FAR * readfds, fd_set FAR * writefds, 
fd_set FAR *exceptfds, const struct timeval FAR * timeout );
◆先来看看涉及到的结构的定义Q?br>a?d_setl构Q?br>
#define FD_SETSIZE 64?
typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;      
fd_count为已讑֮socket的数?br>fd_array为socket列表QFD_SETSIZE为最大socket数量Q徏议不于64。这是微软徏
议的?br>
B、timevall构Q?
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
tv_sec为时间的U倹{?br>tv_usec为时间的毫秒倹{?br>q个l构主要是设|select()函数的等待|如果该l构讄?0,0)Q则select()函数
会立卌回?br>
◆再来看看select函数各参数的作用Q?
  1. nfdsQ没有Q何用处,主要用来q行pȝ兼容用,一般设|ؓ0?br>
  2. readfdsQ等待可L检查的套接字组?br>
  3. writefdsQ等待可写性检查的套接字组?br>
  4. exceptfdsQ等待错误检查的套接字组?br>
  5. timeoutQ超时时间?br>
  6. 函数p|的返回|调用p|q回SOCKET_ERROR,时q回0?
readfds、writefds、exceptfds三个变量臛_有一个不为空Q同时这个不为空的套接字l?br>U至有一个socketQ道理很单,否则要selectq什么呢?举例Q测试一个套接字是否可读Q?
fd_set fdread;
//FD_ZERO定义
// #define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0)
FD_ZERO(&fdread);
FD_SET(s,&fdread)Q?//加入套接字,详细定义Lwinsock2.h
if(select(0,%fdread,NULL,NULL,NULL)>0
{
//成功
if(FD_ISSET(s,&fread) //是否存在fread中,详细定义Lwinsock2.h
{
//是可ȝ
}
}

◆I/O操作函数Q主要用于获取与套接字相关的操作参数?

 int  ioctlsocket(SOCKET s, long cmd, u_long FAR * argp );     
s为I/O操作的套接字?br>cmd为对套接字的操作命o?br>argp为命令所带参数的指针?br>
常见的命令:
//定套接字自动读入的数据?
#define FIONREAD _IOR(''''f'''', 127, u_long) /* get # bytes to read */
//允许或禁止套接字的非d模式Q允ؓ?Q禁止ؓ0
#define FIONBIO _IOW(''''f'''', 126, u_long) /* set/clear non-blocking i/o */
//定是否所有带外数据都已被d
#define SIOCATMARK _IOR(''''s'''', 7, u_long) /* at oob mark? */
3、WSAAsynSelect模型Q?br>WSAAsynSelect模型也是一个常用的异步I/O模型。应用程序可以在一个套接字上接收以
WINDOWS消息为基的网l事仉知。该模型的实现方法是通过调用WSAAsynSelect?br>?自动套接字讄为非d模式Qƈ向WINDOWS注册一个或多个|络旉Qƈ提供一
个通知时用的H口句柄。当注册的事件发生时Q对应的H口收C个基于消息的通知?br>
      int  WSAAsyncSelect( SOCKET s, HWND hWnd, u_int wMsg, long lEvent);       
s为需要事仉知的套接字
hWnd为接收消息的H口句柄
wMsg接收的消?br>lEvent为掩码,指定应用E序感兴的|络事gl合Q主要如下:
#define FD_READ_BIT 0
#define FD_READ (1 << FD_READ_BIT)
#define FD_WRITE_BIT 1
#define FD_WRITE (1 << FD_WRITE_BIT)
#define FD_OOB_BIT 2
#define FD_OOB (1 << FD_OOB_BIT)
#define FD_ACCEPT_BIT 3
#define FD_ACCEPT (1 << FD_ACCEPT_BIT)
#define FD_CONNECT_BIT 4
#define FD_CONNECT (1 << FD_CONNECT_BIT)
#define FD_CLOSE_BIT 5
#define FD_CLOSE (1 << FD_CLOSE_BIT)
用法Q要接收d通知Q?
int nResult= WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE)Q?
if(nResult==SOCKET_ERROR)
{
//错误处理
}
取消通知Q?br>
      int nResult= WSAAsyncSelect(s,hWnd,0Q?)Q?
当应用程序窗口hWnd收到消息ӞwMsg.wParam参数标识了套接字QlParam的低字标?br>了网l事Ӟ高字则包含错误代码?br>
4、WSAEventSelect模型
WSAEventSelect模型cMWSAAsynSelect模型Q但最主要的区别是|络事g发生时会被发
送到一个事件对象句柄,而不是发送到一个窗口?br>
使用步骤如下Q?br>a?创徏事g对象来接收网l事Ӟ
#define WSAEVENT HANDLE
#define LPWSAEVENT LPHANDLE
WSAEVENT WSACreateEvent( void );
该函数的q回gؓ一个事件对象句柄,它具有两U工作状态:已传?signaled)和未传信
(nonsignaled)以及两种工作模式Qh工重?manual reset)和自动重?auto reset)。默认未
未传信的工作状态和人工重设模式?br>
b、将事g对象与套接字兌Q同时注册事Ӟ使事件对象的工作状态从未传信{变未
已传信?br>
      int  WSAEventSelect( SOCKET s,WSAEVENT hEventObject,long lNetworkEvents );  
s为套接字
hEventObject为刚才创建的事g对象句柄
lNetworkEvents为掩码,定义如上面所q?br>
c、I/O处理后,讄事g对象为未传信
BOOL WSAResetEvent( WSAEVENT hEvent );

HeventZ件对?br>
成功q回TRUEQ失败返回FALSE?br>
d、等待网l事件来触发事g句柄的工作状态:

DWORD WSAWaitForMultipleEvents( DWORD cEvents,
const WSAEVENT FAR * lphEvents, BOOL fWaitAll,
DWORD dwTimeout, BOOL fAlertable );

lpEventZ件句柄数l的指针
cEventZؓ事g句柄的数目,其最大gؓWSA_MAXIMUM_WAIT_EVENTS 
fWaitAll指定{待cdQTRUEQ当lphEvent数组重所有事件对象同时有信号时返回;
FALSEQQ一事g有信号就q回?br>dwTimeout为等待超Ӟ毫秒Q?br>fAlertable为指定函数返回时是否执行完成例程

对事件数l中的事件进行引用时Q应该用WSAWaitForMultipleEvents的返回|减去
预声明值WSA_WAIT_EVENT_0Q得到具体的引用倹{例如:

nIndex=WSAWaitForMultipleEvents(…);
MyEvent=EventArray[Index- WSA_WAIT_EVENT_0];

e、判断网l事件类型:

int WSAEnumNetworkEvents( SOCKET s,
WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents );

s为套接字
hEventObject为需要重讄事g对象
lpNetworkEvents录网l事件和错误代码Q其l构定义如下Q?/p>

typedef struct _WSANETWORKEVENTS {
long lNetworkEvents;
int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;

f、关闭事件对象句柄:

BOOL WSACloseEvent(WSAEVENT hEvent);

调用成功q回TRUEQ否则返回FALSE?br>



沛沛 2011-05-03 15:44 发表评论
]]>
Socket ~程http://www.shnenglu.com/mmdengwo/archive/2011/04/29/145307.html沛沛沛沛Fri, 29 Apr 2011 03:18:00 GMThttp://www.shnenglu.com/mmdengwo/archive/2011/04/29/145307.htmlhttp://www.shnenglu.com/mmdengwo/comments/145307.htmlhttp://www.shnenglu.com/mmdengwo/archive/2011/04/29/145307.html#Feedback0http://www.shnenglu.com/mmdengwo/comments/commentRss/145307.htmlhttp://www.shnenglu.com/mmdengwo/services/trackbacks/145307.htmlSocketQ套接字Q?/p>

◆先看定义:
typedef unsigned int u_int;
typedef u_int SOCKET;◆Socket相当于进行网l通信两端的插座,只要Ҏ的Socket和自qSocket有通信联接Q双方就可以发送和接收数据了。其定义cM于文件句柄的定义?/p>

◆Socket有五U不同的cdQ?/p>

1、流式套接字(stream socket)
定义Q?/p>

#define SOCK_STREAM 1 式套接字提供了双向、有序的、无重复的以及无记录边界的数据流服务Q适合处理大量数据。它是面向联l的Q必d立数据传输链路,同时q必d传输的数据进行验证,保数据的准性。因此,pȝ开销较大?/p>

2?数据报套接字(datagram socket)

定义Q?/p>

#define SOCK_DGRAM 2 数据报套接字也支持双向的数据,但不保证传输数据的准性,但保留了记录边界。由于数据报套接字是无联接的Q例如广播时的联接,所以ƈ不保证接收端是否正在侦听。数据报套接字传输效率比较高?/p>

3、原始套接字(raw-protocol interface)

定义Q?/p>

#define SOCK_RAW 3 原始套接字保存了数据包中的完整IP_前面两种套接字只能收到用h据。因此可以通过原始套接字对数据q行分析?br>其它两种套接字不常用Q这里就不介l了?/p>

◆Socket开发所必须需要的文g(以WinSock V2.0Z)Q?/p>

头文ӞWinsock2.h

库文ӞWS2_32.LIB

动态库QW32_32.DLL

 一些重要的定义

1、数据类型的基本定义Q这个大家一看就懂?/p>

typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;2?|络地址的数据结构,有一个老的和一个新的的Q请大家留意Q如果想知道Z么,
请发邮glBill Gate。其实就是计机的IP地址Q不q一般不用用点分开的IP?br>址Q当然也提供一些{换函数?/p>

?旧的|络地址l构的定义,Z?字节的联合:

struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
//下面几行省略,反正没什么用处?br>};其实完全不用q么ȝQ请看下?

?新的|络地址l构的定义:
非常单,是一个无W号长整?unsigned long。D个例子:IP地址?27.0.0.1的网l地址是什么呢Q请看定义:

#define INADDR_LOOPBACK 0x7f0000013?套接字地址l构

(1)、sockaddrl构Q?/p>

struct sockaddr {
u_short sa_family; /* address family */
char sa_data[14]; /* up to 14 bytes of direct address */
};sa_family为网l地址cdQ一般ؓAF_INETQ表Csocket在Internet域中q行通信Q该地址l构随选择的协议的不同而变化,因此一般情况下另一个与该地址l构大小相同的sockaddr_inl构更ؓ常用Qsockaddr_inl构用来标识TCP/IP协议下的地址。换句话_q个l构是通用socket地址l构Q而下面的sockaddr_in是专门针对Internet域的socket地址l构?/p>

(2)、sockaddr_inl构

struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};sin _family为网l地址cdQ必设定ؓAF_INET。sin_port为服务端口,注意不要使用已固定的服务端口Q如HTTP的端?0{。如果端口设|ؓ0Q则pȝ会自动分配一个唯一端口。sin_addrZ个unsigned long的IP地址。sin_zero为填充字D,Ua用来保证l构的大?/p>

?常用的用点分开的IP地址转换为unsigned longcd的IP地址的函敎ͼ

unsigned long inet_addr(const char FAR * cp )用法Q?/p>

unsigned long addr=inet_addr("192.1.8.84")?如果sin_addr讄为INADDR_ANYQ则表示所有的IP地址Q也x有的计算机?/p>

#define INADDR_ANY (u_long)0x000000004?L地址Q?/p>

先看定义Q?/p>

struct hostent {
char FAR * h_name; /* official name of host */
char FAR * FAR * h_aliases; /* alias list */
short h_addrtype; /* host address type */
short h_length; /* length of address */
char FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr h_addr_list[0] /* address, for backward compat */
};
h_nameZ机名字?br>h_aliasesZ机别名列表?br>h_addrtype为地址cd?br>h_length为地址cd?br>h_addr_list为IP地址Q如果该L有多个网卡,包括地址的列表。另外还有几个类似的l构Q这里就不一一介绍了?/p>

5?常见TCP/IP协议的定义:

#define IPPROTO_IP 0
#define IPPROTO_ICMP 1
#define IPPROTO_IGMP 2
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_RAW 255 具体是什么协议,大家一看就知道了?/p>

 套接字的属?/p>

Z灉|使用套接字,我们可以对它的属性进行设定?/p>

1?属性内容:

//允许调试输出
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
//是否监听模式
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
//套接字与其他套接字的地址l定
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
//保持q接
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
//不要路由出去
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
//讄为广?br>#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
//使用环回不通过g
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
//当前拖g?br>#define SO_LINGER 0x0080 /* linger on close if data present */
//是否加入带外数据
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
//用LINGER选项
#define SO_DONTLINGER (int)(~SO_LINGER)
//发送缓冲区长度
#define SO_SNDBUF 0x1001 /* send buffer size */
//接收~冲区长?br>#define SO_RCVBUF 0x1002 /* receive buffer size */
//发送超时时?br>#define SO_SNDTIMEO 0x1005 /* send timeout */
//接收时旉
#define SO_RCVTIMEO 0x1006 /* receive timeout */
//错误状?br>#define SO_ERROR 0x1007 /* get error status and clear */
//套接字类?br>#define SO_TYPE 0x1008 /* get socket type */2?dsocket属性:

int getsockopt(SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)s为欲d属性的套接字。level为套接字选项的别,大多数是特定协议和套接字专有的。如IP协议应ؓ IPPROTO_IP?/p>

optname取选项的名U?br>optval为存N项值的~冲区指针?br>optlen为缓冲区的长度用法:

int ttl=0; //dTTL?br>int rc = getsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));
//来自MS platform SDK 20033?讄socket属性:

int setsockopt(SOCKET s,int level, int optname,const char FAR * optval, int optlen)s为欲讄属性的套接字?br>level为套接字选项的别,用法同上?br>optname|选项的名U?br>optval为存N项值的~冲区指针?br>optlen为缓冲区的长?/p>

用法Q?/p>

int ttl=32; //讄TTL?br>int rc = setsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl)); 套接字的使用步骤

1、启动WinsockQ对Winsock DLLq行初始化,协商Winsock的版本支持ƈ分配必要?br>资源。(服务器端和客LQ?/p>

int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData )

wVersionRequested为打加载Winsock的版本,一般如下设|:
wVersionRequested=MAKEWORD(2,0)
或者直接赋|wVersionRequested=2

LPWSADATA为初始化Socket后加载的版本的信?定义如下Q?br>typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
} WSADATA, FAR * LPWSADATA;如果加蝲成功后数据ؓQ?/p>

wVersionQ?表示加蝲版本?.0?br>wHighVersionQ?14表示当前pȝ支持socket最高版本ؓ2.2?br>szDescription="WinSock 2.0"
szSystemStatus="Running"表示正在q行?br>iMaxSocketsQ?表示同时打开的socket最大数Qؓ0表示没有限制?br>iMaxUdpDgQ?表示同时打开的数据报最大数Qؓ0表示没有限制?br>lpVendorInfo没有使用Qؓ厂商指定信息预留。该函数使用ҎQ?/p>

WORD wVersion=MAKEWORD(2,0);
WSADATA wsData;
int nResult= WSAStartup(wVersion,&wsData);
if(nResult !=0)
{
//错误处理
}2、创建套接字Q(服务器端和客LQ?/p>

SOCKET socket( int af, int type, int protocol );
af为网l地址cdQ一般ؓAF_INETQ表C在Internet域中使用?br>type为套接字cdQ前面已l介l了?br>protocol为指定网l协议,一般ؓIPPROTO_IP。用法:

SOCKET sock=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(sock==INVALID_SOCKET)
{
//错误处理
}3、套接字的绑定:本地地址l定到所创徏的套接字上。(服务器端和客LQ?/p>

int bind( SOCKET s, const struct sockaddr FAR * name, int namelen )
s为已l创建的套接字?br>name为socket地址l构Qؓsockaddrl构Q如前面讨论的,我们一般用sockaddr_in
l构Q在使用再强制{换ؓsockaddrl构?br>namelen为地址l构的长度?br>用法Q?/p>

sockaddr_in addr;
addr. sin_family=AF_INET;
addr. sin_port= htons(0); //保证字节序
addr. sin_addr.s_addr= inet_addr("192.1.8.84")
int nResult=bind(s,(sockaddr*)&addr,sizeof(sockaddr));
if(nResult==SOCKET_ERROR)
{
//错误处理
}4?套接字的监听Q(服务器端Q?/p>

int listen(SOCKET s, int backlog )sZ个已l定但未联接的套接字?br>backlog为指定正在等待联接的最大队列长度,q个参数非常重要Q因为服务器一般可
以提供多个连接?br>用法Q?/p>

int nResult=listen(s,5) //最?个连?br>if(nResult==SOCKET_ERROR)
{
//错误处理
}5、套接字{待q接:Q(服务器端Q?/p>

SOCKET accept( SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen )s为处于监听模式的套接字?br>sockaddr为接收成功后q回客户端的|络地址?br>addrlen为网l地址的长度?/p>

用法Q?/p>

sockaddr_in addr;
SOCKET s_d=accept(s,(sockaddr*)&addr,sizeof(sockaddr));
if(s==INVALID_SOCKET)
{
//错误处理
}6、套接字的连l:两个套接字q结h准备通信。(客户端)

int connect(SOCKET s, const struct sockaddr FAR * name, int namelen )s为欲q结的已创徏的套接字?br>name为欲q结的socket地址?br>namelen为socket地址的结构的长度?/p>

用法Q?/p>

sockaddr_in addr;
addr. sin_family=AF_INET;
addr. sin_port=htons(0); //保证字节序
addr. sin_addr.s_addr= htonl(INADDR_ANY) //保证字节序
int nResult=connect(s,(sockaddr*)&addr,sizeof(sockaddr));
if(nResult==SOCKET_ERROR)
{
//错误处理
}7、套接字发送数据:Q服务器端和客户端)

int send(SOCKET s, const char FAR * buf, int len, int flags )s为服务器端监听的套接字?br>buf为欲发送数据缓冲区的指针?br>len为发送数据缓冲区的长度?br>flags为数据发送标记?br>q回gؓ发送数据的字符数?/p>

◆这里讲一下这个发送标讎ͼ下面8中讨论的接收标记也一P

flag取值必Mؓ0或者如下定义的l合Q?表示没有Ҏ行ؓ?/p>

#define MSG_OOB 0x1 /* process out-of-band data */
#define MSG_PEEK 0x2 /* peek at incoming message */
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
MSG_OOB表示数据应该带外发送,所谓带外数据就是TCP紧急数据?br>MSG_PEEK表示使有用的数据复制到缓冲区内,但ƈ不从pȝ~冲区内删除?br>MSG_DONTROUTE表示不要包路由出去?/p>

用法Q?/p>

char buf[]="xiaojin";
int nResult=send(s,buf,strlen(buf));
if(nResult==SOCKET_ERROR)
{
//错误处理
}8?套接字的数据接收Q(客户端)

int recv( SOCKET s, char FAR * buf, int len, int flags )s为准备接收数据的套接字?br>buf为准备接收数据的~冲区?br>len为准备接收数据缓冲区的大?br>flags为数据接收标记?br>q回gؓ接收的数据的字符数?/p>

用法Q?/p>

char mess[1000];
int nResult =recv(s,mess,1000,0);
if(nResult==SOCKET_ERROR)
{
//错误处理
}9、中断套接字q接Q通知服务器端或客L停止接收和发送数据。(服务器端和客LQ?/p>

int shutdown(SOCKET s, int how)s为欲中断q接的套接字?br>How为描q禁止哪些操作,取gؓQSD_RECEIVE、SD_SEND、SD_BOTH?/p>

#define SD_RECEIVE 0x00
#define SD_SEND 0x01
#define SD_BOTH 0x02用法Q?/p>

int nResult= shutdown(s,SD_BOTH);
if(nResult==SOCKET_ERROR)
{
//错误处理
}10?关闭套接字:释放所占有的资源。(服务器端和客LQ?/p>

int closesocket( SOCKET s )s为欲关闭的套接字?/p>

用法Q?/p>

int nResult=closesocket(s);
if(nResult==SOCKET_ERROR)
{
//错误处理
}
 

本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/coffeemay/archive/2006/08/05/1023149.aspx



沛沛 2011-04-29 11:18 发表评论
]]>
最通俗显的“IO模式”解?/title><link>http://www.shnenglu.com/mmdengwo/archive/2011/04/14/144255.html</link><dc:creator>沛沛</dc:creator><author>沛沛</author><pubDate>Thu, 14 Apr 2011 14:33:00 GMT</pubDate><guid>http://www.shnenglu.com/mmdengwo/archive/2011/04/14/144255.html</guid><wfw:comment>http://www.shnenglu.com/mmdengwo/comments/144255.html</wfw:comment><comments>http://www.shnenglu.com/mmdengwo/archive/2011/04/14/144255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/mmdengwo/comments/commentRss/144255.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mmdengwo/services/trackbacks/144255.html</trackback:ping><description><![CDATA[[源] Qhttp://hi.baidu.com/firebird/blog/item/f592b3193a02814542a9adeb.html<br><br> <font size=2>    一Qselect模型<br>    二:WSAAsyncSelect模型<br>    三:WSAEventSelect模型<br>    四:Overlapped I/O 事g通知模型<br>    五:Overlapped I/O 完成例程模型<br>    六:IOCP模型</font><br><br>原文名:《基于Delphi的Socket I/O模型全接?nbsp;?<br>老陈有一个在外地工作的女儿,不能l常回来Q老陈和她通过信g联系。他们的信会被邮递员投递到他们的信里?nbsp; <br><br>q和Socket模型非常cM。下面我׃老陈接收信gZ讲解Socket I/O模型?nbsp; <br><br>一Qselect模型  <br><br>老陈非常想看到女儿的信。以至于他每?0分钟׃楼检查信,看是否有奛_的信Q在q种情况下,“下楼查信?#8221;然后回到g耽误了老陈太多的时_以至于老陈无法做其他工作?nbsp; <br><br>select模型和老陈的这U情况非常相|周而复始地L?.....如果有数?.....接收/发?......  <br><br>使用U程来select应该是通用的做法:  <br><br>procedure TListenThread.Execute;  <br>var  <br>  addr : TSockAddrIn;  <br>  fd_read : TFDSet;  <br>  timeout : TTimeVal;  <br>  ASock,  <br>  MainSock : TSocket;  <br>  len, i : Integer;  <br>begin  <br>  MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );  <br>  addr.sin_family := AF_INET;  <br>  addr.sin_port := htons(5678);  <br>  addr.sin_addr.S_addr := htonl(INADDR_ANY);  <br>  bind( MainSock, @addr, sizeof(addr) );  <br>  listen( MainSock, 5 );  <br><br>  while (not Terminated) do  <br>  begin  <br>   FD_ZERO( fd_read );  <br>   FD_SET( MainSock, fd_read );  <br>   timeout.tv_sec := 0;  <br>   timeout.tv_usec := 500;  <br>   if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //臛_?个等待Accept的connection  <br>   begin  <br>    if FD_ISSET( MainSock, fd_read ) then  <br>    begin  <br>    for i:=0 to fd_read.fd_count-1 do //注意Qfd_count <= 64Q?<br>   也就是说select只能同时理最?4个连?nbsp; <br>    begin  <br>     len := sizeof(addr);  <br>     ASock := accept( MainSock, addr, len );  <br>     if ASock <> INVALID_SOCKET then  <br>      ....//为ASock创徏一个新的线E,在新的线E中再不停地select  <br>     end;  <br>    end;     <br>   end;  <br>  end; //while (not self.Terminated)  <br><br>  shutdown( MainSock, SD_BOTH );  <br>  closesocket( MainSock );  <br>end; <br>  <br><br><br>二:WSAAsyncSelect模型  <br><br>后来Q老陈使用了微软公司的新式信箱。这U信非常先q,一旦信里有新的信Ӟ盖茨׃l老陈打电话:喂,大爷Q你有新的信件了Q从此,老陈再也不必频繁上下楼检查信׃Q牙也不gQ你瞅准了,蓝天......不是Q微?.....  <br><br>微Y提供的WSAAsyncSelect模型是q个意思?nbsp; <br><br>WSAAsyncSelect模型是Windows下最单易用的一USocket I/O模型。用这U模型时QWindows会把|络事g以消息的形势通知应用E序?nbsp; <br><br>首先定义一个消息标C常量:  <br><br>const WM_SOCKET = WM_USER + 55; <br>  <br><br><br>再在主Form的private域添加一个处理此消息的函数声明:  <br><br>private  <br>procedure WMSocket(var Msg: TMessage); message WM_SOCKET; <br>  <br>   <br><br>然后可以用WSAAsyncSelect了:  <br><br>var  <br>  addr : TSockAddr;  <br>  sock : TSocket;  <br><br>  sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );  <br>  addr.sin_family := AF_INET;  <br>  addr.sin_port := htons(5678);  <br>  addr.sin_addr.S_addr := htonl(INADDR_ANY);  <br>  bind( m_sock, @addr, sizeof(SOCKADDR) );  <br><br>  WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE );  <br><br>  listen( m_sock, 5 );  <br>  .... <br>  <br><br><br>应用E序可以Ҏ到WM_SOCKET消息q行分析Q判断是哪一个socket产生了网l事件以及事件类型:  <br><br>procedure TfmMain.WMSocket(var Msg: TMessage);  <br>var  <br>  sock : TSocket;  <br>  addr : TSockAddrIn;  <br>  addrlen : Integer;  <br>  buf : Array [0..4095] of Char;  <br>begin  <br>  //Msg的WParam是生了|络事g的socket句柄QLParam则包含了事gcd  <br>  case WSAGetSelectEvent( Msg.LParam ) of  <br>  FD_ACCEPT :  <br>   begin  <br>    addrlen := sizeof(addr);  <br>    sock := accept( Msg.WParam, addr, addrlen );  <br>    if sock <> INVALID_SOCKET then  <br>     WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );  <br>   end;  <br><br>   FD_CLOSE : closesocket( Msg.WParam );  <br>   FD_READ : recv( Msg.WParam, buf[0], 4096, 0 );  <br>   FD_WRITE : ;  <br>  end;  <br>end; <br>  <br><br><br>三:WSAEventSelect模型  <br><br>后来Q微软的信箱非常畅销Q购买微软信qZ百万计数......以至于盖茨每?4时l客h电话Q篏得腰酸背痛,喝蚁力神都不好。微软改q了他们的信:在客L家中d一个附加装|,q个装置会监视客L信箱Q每当新的信件来_此装|会发出“C件到?#8221;壎ͼ提醒老陈L信。盖茨终于可以睡觉了?nbsp; <br><br>同样要用线E:  <br><br>procedure TListenThread.Execute;  <br>var  <br>  hEvent : WSAEvent;  <br>  ret : Integer;  <br>  ne : TWSANetworkEvents;  <br>  sock : TSocket;  <br>  adr : TSockAddrIn;  <br>  sMsg : String;  <br>  Index,  <br>  EventTotal : DWORD;  <br>  EventArray : Array [0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT;  <br>begin  <br>  ...socket...bind...  <br>  hEvent := WSACreateEvent();  <br>  WSAEventSelect( ListenSock, hEvent, FD_ACCEPT or FD_CLOSE );  <br>  ...listen...  <br><br>  while ( not Terminated ) do  <br>  begin  <br>   Index := WSAWaitForMultipleEvents( EventTotal, @EventArray[0], FALSE,  <br>  WSA_INFINITE, FALSE );  <br>   FillChar( ne, sizeof(ne), 0 );  <br>   WSAEnumNetworkEvents( SockArray[Index-WSA_WAIT_EVENT_0],  <br>    EventArray <br>  [Index-WSA_WAIT_EVENT_0], @ne );  <br><br>   if ( ne.lNetworkEvents and FD_ACCEPT ) > 0 then  <br>   begin  <br>    if ne.iErrorCode[FD_ACCEPT_BIT] <> 0 then  <br>     continue;  <br><br>    ret := sizeof(adr);  <br>    sock := accept( SockArray[Index-WSA_WAIT_EVENT_0], adr, ret );  <br>    if EventTotal > WSA_MAXIMUM_WAIT_EVENTS-1 then <br>      //q里WSA_MAXIMUM_WAIT_EVENTS同样?4  <br>    begin  <br>     closesocket( sock );  <br>     continue;  <br>    end;  <br><br>    hEvent := WSACreateEvent();  <br>    WSAEventSelect( sock, hEvent, FD_READ or FD_WRITE or FD_CLOSE );  <br>    SockArray[EventTotal] := sock;  <br>    EventArray[EventTotal] := hEvent;  <br>    Inc( EventTotal );  <br>   end;  <br><br>   if ( ne.lNetworkEvents and FD_READ ) > 0 then  <br>   begin  <br>    if ne.iErrorCode[FD_READ_BIT] <> 0 then  <br>     continue;  <br>     FillChar( RecvBuf[0], PACK_SIZE_RECEIVE, 0 );  <br>     ret := recv( SockArray[Index-WSA_WAIT_EVENT_0], RecvBuf[0],  <br>    PACK_SIZE_RECEIVE, 0 );  <br>     ......  <br>    end;  <br>   end;  <br>end; <br>  <br><br><br><br>四:Overlapped I/O 事g通知模型  <br><br>后来Q微软通过调查发现Q老陈不喜Ƣ上下楼收发信gQ因Z下楼其实很浪Ҏ间。于是微软再ơ改q他们的信箱。新式的信箱采用了更为先q的技术,只要用户告诉微Y自己的家在几楼几P新式信箱会把信g直接传送到用户的家中,然后告诉用户Q你的信件已l放C的家中了Q老陈很高_因ؓ他不必再亲自收发信g了!  <br><br>Overlapped I/O 事g通知模型和WSAEventSelect模型在实C非常怼Q主要区别在"Overlapped”QOverlapped模型是让应用E序使用重叠数据l构(WSAOVERLAPPED)Q一ơ投递一个或多个Winsock I/Oh。这些提交的h完成后,应用E序会收到通知。什么意思呢Q就是说Q如果你想从socket上接收数据,只需要告诉系l,qlؓ你接收数据,而你需要做的只是ؓpȝ提供一个缓冲区~~~~~  <br><br>ListenU程和WSAEventSelect模型一模一PRecv/SendU程则完全不同:  <br><br>procedure TOverlapThread.Execute;  <br>var  <br>  dwTemp : DWORD;  <br>  ret : Integer;  <br>  Index : DWORD;  <br>begin  <br>  ......  <br><br>  while ( not Terminated ) do  <br>  begin  <br>   Index := WSAWaitForMultipleEvents <br>   ( FLinks.Count, @FLinks.Events[0], FALSE,  <br>    RECV_TIME_OUT, FALSE );  <br>   Dec( Index, WSA_WAIT_EVENT_0 );  <br>   if Index > WSA_MAXIMUM_WAIT_EVENTS-1 then  <br>    //时或者其他错?nbsp; <br>    continue;  <br><br>   WSAResetEvent <br>   ( FLinks.Events[Index] );  <br>   WSAGetOverlappedResult( FLinks.Sockets[Index],  <br>      FLinks.pOverlaps[Index], @dwTemp, FALSE,FLinks. <br>     pdwFlags[Index]^ );  <br><br>   if dwTemp = 0 then //q接已经关闭  <br>   begin  <br>    ......  <br>    continue;  <br>   end else  <br>  begin  <br>   fmMain.ListBox1.Items.Add( FLinks.pBufs[Index]^.buf );  <br>  end;  <br><br>  //初始化缓冲区  <br>  FLinks.pdwFlags[Index]^ := 0;  <br>  FillChar( FLinks.pOverlaps[Index]^,  <br>    sizeof(WSAOVERLAPPED), 0 );  <br>  FLinks.pOverlaps[Index]^. <br>   hEvent := FLinks.Events[Index];  <br>  FillChar( FLinks.pBufs[Index]^.buf^,  <br>   BUFFER_SIZE, 0 );  <br><br>  //递一个接收数据请?nbsp; <br>  WSARecv( FLinks.Sockets[Index], FLinks.pBufs[Index], 1, <br>       FLinks.pdwRecvd[Index]^, FLinks.pdwFlags[Index]^,  <br>      FLinks.pOverlaps[Index], nil );  <br>end;  <br>end; <br>  <br><br><br>五:Overlapped I/O 完成例程模型  <br><br>老陈接收到新的信件后Q一般的E序是:打开信封----掏出信纸----阅读信g----回复信g......Zq一步减ȝ戯担,微Y又开发了一U新的技术:用户只要告诉微Y对信件的操作步骤Q微软信将按照q些步骤d理信Ӟ不再需要用户亲自拆?阅读/回复了!老陈l于q上了小资生z!  <br><br>Overlapped I/O 完成例程要求用户提供一个回调函敎ͼ发生新的|络事g的时候系l将执行q个函数Q?nbsp; <br><br>procedure WorkerRoutine( const dwError, cbTransferred : DWORD;  <br>const  <br>lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall; <br>  <br><br><br>然后告诉pȝ用WorkerRoutine函数处理接收到的数据Q?nbsp; <br><br>WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );  <br>   然后......没有什么然后了Q系l什么都l你做了Q微软真实体_  <br><br>while ( not Terminated ) do//q就是一个Recv/SendU程要做的事?.....什么都不用做啊Q!Q?nbsp; <br>begin  <br>  if SleepEx( RECV_TIME_OUT, True ) = WAIT_IO_COMPLETION then //  <br>  begin  <br>   ;  <br>  end else  <br>  begin  <br>   continue;  <br>  end;  <br>end; <br>  <br><br><br>六:IOCP模型  <br><br>微Y信箱g很完,老陈也很满意。但是在一些大公司情况却完全不同!q些大公司有C万计的信,每秒钟都有数以百计的信g需要处理,以至于微软信q常因负药转而崩溃!需要重新启动!微Y不得不出杀手锏......  <br><br>微Yl每个大公司z了一名名?#8220;Completion Port”的超U机器hQ让q个机器人去处理那些信gQ?nbsp; <br><br>“Windows NT组注意到这些应用程序的性能没有预料的那么高。特别的Q处理很多同时的客户h意味着很多U程q发地运行在pȝ中。因为所有这些线E都是可q行的[没有被挂起和{待发生什么事]QMicrosoft意识到NT内核p了太多的旉来{换运行线E的上下文[Context]Q线E就没有得到很多CPU旉来做它们的工作。大家可能也都感觉到q行模型的瓶颈在于它为每一个客戯求都创徏了一个新U程。创建线E比起创E开销要小Q但也远不是没有开销的。我们不妨设想一下:如果事先开好N个线E,让它们在那hold[堵塞]Q然后可以将所有用Lh都投递到一个消息队列中厅R然后那N个线E逐一从消息队列中d出消息ƈ加以处理。就可以避免针对每一个用戯求都开U程。不仅减了U程的资源,也提高了U程的利用率。理Z很不错,你想我等泛泛之辈都能惛_来的问题QMicrosoft又怎会没有考虑到呢?”-----摘自nonocast的《理解I/O Completion Port?nbsp; <br><br>先看一下IOCP模型的实玎ͼ  <br><br>//创徏一个完成端?nbsp; <br>FCompletPort := CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0,0,0 );  <br><br>//接受q程q接Qƈ把这个连接的socket句柄l定到刚才创建的IOCP?nbsp; <br>AConnect := accept( FListenSock, addr, len);  <br>CreateIoCompletionPort( AConnect, FCompletPort, nil, 0 );  <br><br>//创徏CPU?2 + 2个线E?nbsp; <br>for i:=1 to si.dwNumberOfProcessors*2+2 do  <br>begin  <br>  AThread := TRecvSendThread.Create( false );  <br>  AThread.CompletPort := FCompletPort;//告诉q个U程Q你要去q个IOCP去访问数?nbsp; <br>end; <br>  <br><br><br>p么简单,我们要做的就是徏立一个IOCPQ把q程q接的socket句柄l定到刚才创建的IOCP上,最后创建n个线E,q告诉这n个线E到q个IOCP上去讉K数据可以了?nbsp; <br><br>再看一下TRecvSendThreadU程都干些什么:  <br><br>procedure TRecvSendThread.Execute;  <br>var  <br>  ......  <br>begin  <br>  while (not self.Terminated) do  <br>  begin  <br>   //查询IOCP状态(数据d操作是否完成Q?nbsp; <br>   GetQueuedCompletionStatus( CompletPort, BytesTransd,  <br>    CompletKey, POVERLAPPED(pPerIoDat), TIME_OUT );  <br><br>   if BytesTransd <> 0 then  <br>    ....;//数据d操作完成  <br>    <br>    //再投递一个读数据h  <br>    WSARecv( CompletKey, @(pPerIoDat^.BufData), 1,  <br>    BytesRecv, Flags, @(pPerIoDat^.Overlap), nil );  <br>   end;  <br>end; <br>  <br><br><br>dU程只是单地查IOCP是否完成了我们投递的d操作Q如果完成了则再投递一个新的读写请求?nbsp; <br><br>应该注意刎ͼ我们创徏的所有TRecvSendThread都在讉K同一个IOCPQ因为我们只创徏了一个IOCPQ,q且我们没有使用临界区!N不会产生冲突吗?不用考虑同步问题吗?  <br><br>q正是IOCP的奥妙所在。IOCP不是一个普通的对象Q不需要考虑U程安全问题。它会自动调配访问它的线E:如果某个socket上有一个线EA正在讉KQ那么线EB的访问请求会被分配到另外一个socket。这一切都是由pȝ自动调配的,我们无需q问? <img src ="http://www.shnenglu.com/mmdengwo/aggbug/144255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mmdengwo/" target="_blank">沛沛</a> 2011-04-14 22:33 <a href="http://www.shnenglu.com/mmdengwo/archive/2011/04/14/144255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.m20008.cn" target="_blank">ھƷþۺ88 </a>| <a href="http://www.inqh.cn" target="_blank">ƷþĻ</a>| <a href="http://www.ruozhu.com.cn" target="_blank">þ˽˹ƷvA</a>| <a href="http://www.shlinfeng.com.cn" target="_blank">þþþһ</a>| <a href="http://www.dgwhmnk.cn" target="_blank">þþþþþƷͼƬ</a>| <a href="http://www.chaikuo.cn" target="_blank">AVӰƬþþþþ</a>| <a href="http://www.hasgw.cn" target="_blank">þ޴ɫĻþþ</a>| <a href="http://www.mmexse.cn" target="_blank">ѹۿ˾þѹۿ</a>| <a href="http://www.liaojiaren.cn" target="_blank">ƷþþþþþþþĻ </a>| <a href="http://www.gz2378.cn" target="_blank">ɫþAVۺ</a>| <a href="http://www.zhjcys.cn" target="_blank">51þҹɫƷ</a>| <a href="http://www.csrencaiwd.cn" target="_blank">þþþAVۺ</a>| <a href="http://www.force-equipment.com.cn" target="_blank">þAV뾫Ʒɫҹ </a>| <a href="http://www.theys.cn" target="_blank">պʮ˽һþ</a>| <a href="http://www.xiatiancaiwu.cn" target="_blank">AVþ</a>| <a href="http://www.duansisi.cn" target="_blank">99Ʒþþþþþ</a>| <a href="http://www.gay2000.cn" target="_blank">þ޹ƷAVϼ </a>| <a href="http://www.umw.net.cn" target="_blank">þþþ</a>| <a href="http://www.wyj448.cn" target="_blank">þۺ͵͵ɫ</a>| <a href="http://www.r97n59.cn" target="_blank">ŷһƷþ</a>| <a href="http://www.pz897.cn" target="_blank">ھƷþ</a>| <a href="http://www.odostudio.cn" target="_blank">˾Ʒþþþ7777</a>| <a href="http://www.woaisheying.cn" target="_blank">ҹþþ</a>| <a href="http://www.hjzz.net.cn" target="_blank">ھƷþþþþþɬ </a>| <a href="http://www.yuzeyuanyi.cn" target="_blank">þeֻйľƷ99 </a>| <a href="http://www.zhidaow.com.cn" target="_blank">ƷѸþ</a>| <a href="http://www.meiguohongfeng.com.cn" target="_blank">þ99þóѲ</a>| <a href="http://www.lglmhdf.cn" target="_blank">ҰĻþ</a>| <a href="http://www.111net.org.cn" target="_blank">þAAAƬ69</a>| <a href="http://www.cqxuexi.cn" target="_blank">þ</a>| <a href="http://www.hnzzwl.cn" target="_blank">ݺɫۺվþþþþþø</a>| <a href="http://www.lslscy.cn" target="_blank">ҹƷþþþþ</a>| <a href="http://www.56dn.cn" target="_blank">97þþþ޾Ʒר</a>| <a href="http://www.jtlyr.cn" target="_blank">˾þô߽槼</a>| <a href="http://www.byzj.net.cn" target="_blank">þԭƷ</a>| <a href="http://www.reln.cn" target="_blank">޾ƷƷþ99һ</a>| <a href="http://www.czyhfzc.cn" target="_blank">þҹɫƷa</a>| <a href="http://www.kftfk.cn" target="_blank">ѾþþƷ99reѾy</a>| <a href="http://www.airgig.net.cn" target="_blank">þֻǾƷ66</a>| <a href="http://www.bbs020.cn" target="_blank">þùAV䡪ٶ</a>| <a href="http://www.ndali.cn" target="_blank">͵ٸþþþþþþ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>