这个例子很简单,服务端是单线程的,一般来说实际应用中多采用多线程方式监听客户请求的。
先列客户端的代码:Client.h
#ifndef _SERVERSOCKET_H
#define _SERVERSOCKET_H
#i nclude <sys/types.h>
//! 下面是根据操作系统自动加载所需的库和头文件
#ifdef WIN32
#i nclude <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#else
#i nclude <sys/socket.h>
#endif
#i nclude <string>
#i nclude <iostream>
int WSAStartup
(
WORD wVersionRequested,
LPWSADATA lpWSAData
);

using namespace std;
class CClient
 ...{
int m_sockfd;
struct sockaddr_in m_addr;
public:
CClient(const string& strAddr, int iPort);
~CClient();
BOOL Connect();
};
#endif |
定义文件Client.cpp
#i nclude
"
Client.h
"
CClient::CClient(
const
string
&
strAddr,
int
iPort)

...
{
WSADATA wsaData;
int err = WSAStartup( MAKEWORD(2, 2), &wsaData );
if (err == SOCKET_ERROR)
cout << "WSAStartup error" << endl;
m_sockfd
=
socket(AF_INET, SOCK_STREAM,
0
);
/*需要错误检查 */
if
(m_sockfd
==
-
1
)

...
{
cout << "socket fail!" << endl;
return;
}
cout
<<
"
socket success!socket:
"
<<
m_sockfd
<<
endl;
memset(
&
m_addr,
0x00
,
sizeof
(m_addr));

m_addr.sin_family
=
AF_INET;
/**/
/* host byte order */

m_addr.sin_port
=
htons(iPort);
/**/
/* short, network byte order */
m_addr.sin_addr.s_addr
=
inet_addr(strAddr.c_str());
}

CClient::
~
CClient()

...
{
WSACleanup();
}

BOOL CClient::Connect()

...
{
int iRet = connect(m_sockfd, (struct sockaddr *)&m_addr, sizeof(m_addr));
if (iRet == -1)

...{
cout << "connect fail!" << endl;
return FALSE;
}
return TRUE;
}

BOOL CClient::Send(
const
string
&
strSend)

...
{
int iRet = send(m_sockfd, strSend.c_str(), strSend.length(), 0);
if (iRet == -1)

...{
cout << "connect fail!" << endl;
return FALSE;
}
cout << "Send is OK!";
return TRUE;
}
上面的例子中我把较多的初始化处理直接放在了构造函数中,这个习惯不是很好。不过只是一个简单举例,所以我就不修改它了。客户端的主文件如下:
#i nclude
<
stdlib.h
>
#i nclude
"
Client.h
"

int
main(
int
argc,
char
*
argv[])

...
{
CClient cc("127.0.0.1", 8001); //! 第一个参数是本机IP地址,第二参数是自选的端口号
cc.Connect();
cc.Send("Send Message!");
system("PAUSE");
return 0;
}
下面是服务端的头文件:Server.h
#ifndef _SERVERSOCKET_H
#define
_SERVERSOCKET_H
#i nclude
<
sys
/
types.h
>
#ifdef WIN32
#i nclude
<
winsock2.h
>
#pragma
comment(lib,"ws2_32.lib")
#else
#i nclude
<
sys
/
socket.h
>
#endif
#i nclude
<
string
>
#i nclude
<
iostream
>
#define
SERVER_PORT 8001
#define
MAX_BUFFER_LENGTH 2048

using
namespace
std;
class
CServer

...
{
int m_sockfd;
struct sockaddr_in m_addr;public:
CServer(const string& strAddr);
~CServer();
BOOL Start();
BOOL Stop();
}
;
#endif
对应的定义文件:
#i nclude
"
Server.h
"

CServer::CServer(
const
string
&
strAddr)

...
{
WSADATA wsaData;
int err = WSAStartup( MAKEWORD(2, 2), &wsaData );
if (err == SOCKET_ERROR)

...{
cout << "WSAStartup error" << endl;
return;
}

m_sockfd = socket(AF_INET, SOCK_STREAM, 0); /**//*需要错误检查 */

m_addr.sin_family = AF_INET; /**//* host byte order */

m_addr.sin_port = htons(SERVER_PORT); /**//* short, network byte order */
m_addr.sin_addr.s_addr = inet_addr(strAddr.c_str());
}

CServer::
~
CServer()

...
{
WSACleanup();
}

BOOL CServer::Start()

...
{
int iret = bind(m_sockfd, (struct sockaddr *)&m_addr, sizeof(struct sockaddr));
if (iret == -1)

...{
cout << "bind fail" << endl;
return FALSE;
}
cout << "bind OK" << endl;
listen(m_sockfd, 3);
cout << "listening..." << endl;
struct sockaddr_in their_addr;
int sin_size = sizeof(struct sockaddr_in);
int getsockfd = accept(m_sockfd,(struct sockaddr *)&their_addr,&sin_size);
cout << "accepted" << endl;

char buf[MAX_BUFFER_LENGTH] = ...{0};
if (!getsockfd)

...{
return FALSE;
}
cout << "Starting Server...!" << endl;
int recvLen = 0;
do

...{
recvLen = recv(getsockfd, buf, sizeof(buf)/sizeof(buf[0]), 0);
}while(recvLen == -1);
cout << buf << endl;
return TRUE;
}

BOOL CServer::Stop()

...
{
//close(m_sockfd); //! 这个地方如果去掉前面的注释符,编译会报错。
//! 我暂时还没有去了解原因。按道理应该要关闭的。