// 一个监听线程, 每当一个新的客户端连接进来时会再创建一个新的线程供连接
#include
"stdafx.h"
#include
<winsock2.h>
#include
<iostream>
#pragma
comment
(
lib
,
"ws2_32.lib"
)
const
static
int
BUF_SIZE
= 256;
using
namespace
std
;
#define
MAIN_RETURN_ERROR
-1;
#define
MAIN_RETURN_NORMAL
0;
DWORD
WINAPI
AnswerThread
(
LPVOID
lparam
);
sockaddr_in
addrClient
;
int
addrClientLen
=
sizeof
(
addrClient
);
int
_tmain
(
int
argc
,
_TCHAR
*
argv
[])
{
//
初始化
Winsock 2.2
WSADATA
wsaData
;
if
(
WSAStartup
(
MAKEWORD
( 2, 2 ), &
wsaData
) != 0 )
{
cout
<<
"WSAStartup
无法初始化
!"
<<
endl
;
return
MAIN_RETURN_ERROR
;
}
//
通过
WinSock
实现网络通信
SOCKET
sServer
;
//
创建用于监听的
Socket
sServer
=
socket
(
AF_INET
,
SOCK_STREAM
,
IPPROTO_TCP
);
if
(
INVALID_SOCKET
==
sServer
)
{
cout
<<
"Socket Failed !"
<<
endl
;
WSACleanup
();
return
MAIN_RETURN_ERROR
;
}
//
设置服务器
Socket
地址
SOCKADDR_IN
addrServ
;
addrServ
.
sin_family
=
AF_INET
;
addrServ
.
sin_port
=
htons
( 9990 );
//
服务器端口号
addrServ
.
sin_addr
.
S_un
.
S_addr
=
htonl
(
INADDR_ANY
);
//
绑定
int
retVal
;
retVal
=
bind
(
sServer
, (
const
struct
sockaddr
*)&
addrServ
,
sizeof
(
SOCKADDR_IN
) );
if
(
SOCKET_ERROR
==
retVal
)
{
cout
<<
"bind failed !"
<<
endl
;
closesocket
(
sServer
);
WSACleanup
();
return
-1;
}
//
监听
retVal
=
listen
(
sServer
, 1 );
if
(
SOCKET_ERROR
==
retVal
)
{
cout
<<
"listen failed !"
<<
endl
;
closesocket
(
sServer
);
WSACleanup
();
return
-1;
}
//
设置
socket
其为非阻塞模式
, argp
设为非零值
int
iModel
= 1;
retVal
=
ioctlsocket
(
sServer
,
FIONBIO
, (
u_long
FAR
* )&
iModel
);
if
(
SOCKET_ERROR
==
retVal
)
{
cout
<<
"ioctlsocket failed "
<<
endl
;
WSACleanup
();
return
MAIN_RETURN_ERROR
;
}
cout
<<
"TCP Server Start ... ..."
<<
endl
;
//
循环等待
while
(
true
)
{
SOCKET
sClient
=
accept
(
sServer
, (
sockaddr
FAR
*)&
addrClient
, &
addrClientLen
);
if
(
INVALID_SOCKET
==
sClient
)
{
int
err
=
WSAGetLastError
();
if
(
WSAEWOULDBLOCK
==
err
)
//
没接到连接请求
{
Sleep
( 100 );
continue
;
}
else
{
cout
<<
"accept failed"
<<
endl
;
closesocket
(
sServer
);
WSACleanup
();
return
MAIN_RETURN_ERROR
;
}
}
// 接到了创建一个新线程供新的客户端使用
DWORD
dwThreadId
;
CreateThread
(
NULL
,
NULL
,
AnswerThread
, (
LPVOID
)
sClient
, 0, &
dwThreadId
);
}
//
最后做一些清理工作
closesocket
(
sServer
);
WSACleanup
();
system
(
"pause"
);
return
MAIN_RETURN_NORMAL
;
}
DWORD
WINAPI
AnswerThread
(
LPVOID
lparam
)
{
//
循环接受客户端发送来的请求,直到客户端发送
quit
命令
char
buf
[
BUF_SIZE
];
int
retVal
;
SOCKET
sClient
= (
SOCKET
)(
LPVOID
)
lparam
;
while
(
true
)
{
ZeroMemory
(
buf
,
BUF_SIZE
);
retVal
=
recv
(
sClient
,
buf
,
BUF_SIZE
, 0 );
if
(
SOCKET_ERROR
==
retVal
)
{
int
err
=
WSAGetLastError
();
if
(
WSAEWOULDBLOCK
==
err
)
{
Sleep
( 100 );
continue
;
}
else
if
(
WSAETIMEDOUT
==
err
||
WSAENETDOWN
==
err
)
//
网络系统故障
{
cout
<<
"recv failed !"
<<
endl
;
closesocket
(
sClient
);
WSACleanup
();
return
MAIN_RETURN_ERROR
;
}
}
SYSTEMTIME
st
;
GetLocalTime
( &
st
);
char
sDateTime
[30];
sprintf
(
sDateTime
,
"%4d-%2d-%2d %2d:%2d:%2d"
,
st
.
wYear
,
st
.
wMonth
,
st
.
wDay
,
st
.
wHour
,
st
.
wMinute
,
st
.
wSecond
);
cout
<<
sDateTime
<<
" , Recv From Client [ "
<<
inet_ntoa
(
addrClient
.
sin_addr
)<<
":"
<<
addrClient
.
sin_port
<<
"]: "
<<
buf
<<
endl
;
if
( 0 ==
strcmp
(
buf
,
"quit"
) )
{
retVal
=
send
(
sClient
,
"quit"
,
strlen
(
"quit"
), 0 );
break
;
}
else
{
char
msg
[
BUF_SIZE
];
sprintf
(
msg
,
"Message receive - %s "
,
buf
);
while
(
true
)
{
retVal
=
send
(
sClient
,
msg
,
strlen
(
msg
), 0 );
if
(
SOCKET_ERROR
==
retVal
)
{
int
err
=
WSAGetLastError
();
if
(
WSAEWOULDBLOCK
==
err
)
{
Sleep
( 100 );
continue
;
}
else
{
cout
<<
"send failed !"
<<
endl
;
closesocket
(
sClient
);
WSACleanup
();
return
MAIN_RETURN_ERROR
;
}
}
else
break
;
}
}
}
closesocket
(
sClient
);
}