您的位置:首页 > 其它

Windows Socket I/O模型之 Select模式

2011-02-02 14:08 295 查看
#
include
<
winsock2.
h>

#
include
<
ws2tcpip.
h>

#
include
"resolve.h"

#
include
"public.h"

typedef
SINGLE_LIST_HEADER BuffHeader;

typedef
SINGLE_LIST BuffObj;

typedef
DOUBLE_LIST_HEADER SockObjHeader;

typedef
DOUBLE_LIST SockObj;

typedef
struct
_SOCKET_OBJ

{

SOCKET
s;
// Socket handle

int
listening;
// Socket is a listening socket (TCP)

int
closing;
// Indicates whether the connection is closing

SOCKADDR_STORAGE addr;
// Used for client's remote address

int
addrlen;
// Length of the address

BuffHeader  buff;

DOUBLE_LIST entry;

}
SOCKET_OBJ;

SockObjHeader sockobjhead;

SOCKET_OBJ*
GetSocketObj(
SOCKET
s,
int
listening)
{

SOCKET_OBJ *
sockobj =
NULL
;

sockobj =
(
SOCKET_OBJ*
)
HeapAlloc(
GetProcessHeap(
)
,
HEAP_ZERO_MEMORY,
sizeof
(
SOCKET_OBJ)
)
;

if
(
sockobj =
=
NULL
)
{

fprintf
(
stderr
,
"HeapAlloc failed./n"
)
;

ExitProcess(
-
1)
;

}

sockobj-
>
s =
s;

sockobj-
>
listening =
listening;

sockobj-
>
addrlen =
sizeof
(
sockobj-
>
addr)
;

InitializeCriticalSection(
&
sockobj-
>
buff.
SendRecvQueueCritSec)
;

return
sockobj;

}

void
FreeSocketObj(
SOCKET_OBJ *
obj)
{

BuffObj *
ptr =
NULL
;

BUFFER_OBJ *
blk =
NULL
;

while
(
true
)
{

ptr =
DequeueSingleList(
&
obj-
>
buff)
;

if
(
ptr =
=
NULL
)

break
;

blk =
(
BUFFER_OBJ *
)
container_of(
BUFFER_OBJ,
next,
ptr)
;

FreeBufferObj(
blk)
;

}

HeapFree(
GetProcessHeap(
)
,
0,
obj)
;

}

int
ReceivePendingData(
SOCKET_OBJ *
obj)
{

BUFFER_OBJ *
buffobj =
NULL
;

int
rc,
ret;

buffobj =
GetBufferObj(
gBufferSize)
;

ret =
0;

if
(
gProtocol =
=
IPPROTO_TCP
)
{

rc =
recv
(
obj-
>
s,
buffobj-
>
buf,
buffobj-
>
buflen,
0)
;

}
else
{

ExitProcess(
-
1)
;

}

if
(
rc =
=
SOCKET_ERROR)
{

ExitProcess(
-
1)
;

}
else
if
(
rc =
=
0)
{

FreeBufferObj(
buffobj)
;

obj-
>
closing =
TRUE
;

if
(
obj-
>
buff.
head =
=
NULL
)
{

closesocket(
obj-
>
s)
;

ret =
-
1;

}

}
else
{

buffobj-
>
buflen =
rc;

EnqueueSingleList(
&
obj-
>
buff,
&
buffobj-
>
next)
;

}

return
ret;

}

int
SendPendingData(
SOCKET_OBJ *
sock)
{

BUFFER_OBJ *
bufobj =
NULL
;

BuffObj *
entry =
NULL
;

int
nleft =
0,

idx =
0,

ret =
0,

rc =
0;

while
(
entry =
DequeueSingleList(
&
sock-
>
buff)
)
{

bufobj =
(
BUFFER_OBJ *
)
container_of(
BUFFER_OBJ,
next,
entry)
;

if
(
gProtocol =
=
IPPROTO_TCP
)
{

nleft =
bufobj-
>
buflen;

idx =
0;

while
(
nleft >
0)
{

rc =
send
(
sock-
>
s,
&
(
bufobj-
>
buf[
idx]
)
,
nleft,
0)
;

if
(
rc =
=
SOCKET_ERROR)
{

ExitProcess(
-
1)
;

}
else
{

idx +
=
rc;

nleft -
=
rc;

}

}

FreeBufferObj(
bufobj)
;

}
else
{

ExitProcess(
-
1)
;

}

}

if
(
sock-
>
closing =
=
TRUE
)
{

closesocket(
sock-
>
s)
;

ret =
-
1;

printf
(
"Closing Connection./n"
)
;

}

return
ret;

}

int
_tmain(
int
argc,
_TCHAR*
argv[
]
)

{

WSADATA wsd;

SOCKET
s;

struct
addrinfo
*
res =
NULL
;

struct
addrinfo
*
ptr =
NULL
;

SOCKET_OBJ *
sockobj =
NULL
;

int
rc;

struct
fd_set    fdread,
fdwrite,
fdexcept;

struct
timeval
timeout;

if
(
WSAStartup(
MAKEWORD(
2,
2)
,
&
wsd)
!
=
0)
{

fprintf
(
stderr
,
"load winsock2 failed./n"
)
;

return
0;

}

res =
ResolveAddress(
gSrvAddr,
gPort,
gAddressFamily,
gSocketType,
gProtocol)
;

if
(
res =
=
NULL
)
{

fprintf
(
stderr
,
"resolve addr failed./n"
)
;

return
-
1;

}

InitializeDoubleHead(
&
sockobjhead)
;

ptr =
res;

while
(
ptr)
{

s =
socket
(
ptr-
>
ai_family,
ptr-
>
ai_socktype,
ptr-
>
ai_protocol)
;

if
(
s =
=
INVALID_SOCKET)
{

fprintf
(
stderr
,
"create socket failed./n"
)
;

break
;

}

sockobj =
GetSocketObj(
s,
(
gProtocol =
=
IPPROTO_TCP
)
?
TRUE
:
FALSE
)
;

EnqueueDoubleList(
&
sockobjhead,
&
sockobj-
>
entry)
;

rc =
bind
(
sockobj-
>
s,
ptr-
>
ai_addr,
ptr-
>
ai_addrlen)
;

if
(
rc =
=
SOCKET_ERROR)
{

fprintf
(
stderr
,
"bind failed./n"
)
;

return
0;

}

if
(
gProtocol =
=
IPPROTO_TCP
)

{

rc =
listen
(
sockobj-
>
s,
200)
;

if
(
rc =
=
SOCKET_ERROR)

{

fprintf
(
stderr
,
"listen failed: %d/n"
,
WSAGetLastError(
)
)
;

return
-
1;

}

}

ptr =
ptr-
>
ai_next;

}

freeaddrinfo
(
res)
;

while
(
true
)
{

FD_ZERO(
&
fdread)
;

FD_ZERO(
&
fdwrite)
;

FD_ZERO(
&
fdexcept)
;

SockObj *
sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
&
(
sockobjhead.
head)
)
;

SOCKET_OBJ *
obj =
NULL
;

while
(
sptr)
{

obj =
(
SOCKET_OBJ *
)
container_of(
SOCKET_OBJ,
entry,
sptr)
;

FD_SET(
obj-
>
s,
&
fdread)
;

FD_SET(
obj-
>
s,
&
fdwrite)
;

FD_SET(
obj-
>
s,
&
fdexcept)
;

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

}

timeout.
tv_sec =
5;

timeout.
tv_usec =
0;

rc =
select
(
0,
&
fdread,
&
fdwrite,
&
fdexcept,
&
timeout)
;

if
(
rc =
=
SOCKET_ERROR)
{

fprintf
(
stderr
,
"select failed./n"
)
;

return
-
1;

}
else
if
(
rc =
=
0)
{

printf
(
"Wait Time out./n"
)
;

continue
;

}

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
&
(
sockobjhead.
head)
)
;

SockObj *
tmp =
NULL
;

obj =
NULL
;

while
(
sptr)
{

obj =
(
SOCKET_OBJ *
)
container_of(
SOCKET_OBJ,
entry,
sptr)
;

if
(
FD_ISSET(
obj-
>
s,
&
fdread)
)
{

if
(
obj-
>
listening)
{

sockobj =
(
SOCKET_OBJ *
)
GetSocketObj(
INVALID_SOCKET,
FALSE
)
;

s =
accept
(
obj-
>
s,
(
SOCKADDR
*
)
&
sockobj-
>
addr,
&
sockobj-
>
addrlen)
;

if
(
s =
=
INVALID_SOCKET)
{

fprintf
(
stderr
,
"accept failed./n"
)
;

return
-
1;

}

sockobj-
>
s =
s;

EnqueueDoubleListHead(
&
sockobjhead,
&
sockobj-
>
entry)
;

}
else
{

if
(
ReceivePendingData(
obj)
!
=
0)
{

printf
(
"ReceivePendingData./n"
)
;

tmp =
sptr;

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

RemoveDoubleList(
&
sockobjhead,
tmp)
;

FreeSocketObj(
obj)
;

continue
;

}

if
(
SendPendingData(
obj)
!
=
0)
{

tmp =
sptr;

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

RemoveDoubleList(
&
sockobjhead,
tmp)
;

FreeSocketObj(
obj)
;

continue
;

}

}

}

if
(
FD_ISSET(
obj-
>
s,
&
fdwrite)
)
{

if
(
SendPendingData(
obj)
!
=
0)
{

tmp =
sptr;

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

RemoveDoubleList(
&
sockobjhead,
tmp)
;

FreeSocketObj(
obj)
;

continue
;

}

}

if
(
FD_ISSET(
obj-
>
s,
&
fdexcept)
)
{

tmp =
sptr;

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

RemoveDoubleList(
&
sockobjhead,
tmp)
;

FreeSocketObj(
obj)
;

}

sptr =
(
SockObj *
)
GotoNextDoubleList(
&
sockobjhead,
sptr)
;

}

}

WSACleanup(
)
;

return
0;

}


版权声明:
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: