// InitSocket.cpp
#include "stdafx.h"
#include "InitSocket.h"
InitSocket::InitSocket():m_nPort(6666),m_strDefaultServerIP("127.0.0.1"),m_bStartup(false), m_bUseAddrAny(true)
{
}
InitSocket::~InitSocket()
{
if (m_bStartup)
{
::WSACleanup();
}
}
void InitSocket::SetPort(int & nPort)
{
m_nPort = nPort;
}
int & const InitSocket::GetPort()
{
return m_nPort;
}
void InitSocket::SetServerIP(string & IP)
{
m_strDefaultServerIP = IP;
}
string & const InitSocket::GetServerIP()
{
return m_strDefaultServerIP;
}
bool & InitSocket::IsStartUp()
{
return m_bStartup;
}
bool & InitSocket::StartUp()
{
WSADATA wsa;
::WSAStartup(MAKEWORD(2, 2), &wsa);
if (WSAGetLastError() == 0)
{
m_ServerSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET != m_ServerSocket)
{
m_bStartup = true;
}
}
return m_bStartup;
}
void InitSocket::SetWhetherUseAddrAny(bool & use)
{
m_bUseAddrAny = use;
}
bool InitSocket::Bind()
{
if (m_bStartup)
{
sockaddr_in serverInfo;
if (m_bUseAddrAny)
{
serverInfo.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
}
else
{
serverInfo.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
}
serverInfo.sin_family = AF_INET;
serverInfo.sin_port = htons(m_nPort);
::bind(m_ServerSocket, (const sockaddr*)&serverInfo, sizeof(serverInfo));
if (WSAGetLastError() == 0)
{
return true;
}
}
return false;
}
bool InitSocket::Listen()
{
::listen(m_ServerSocket, 5);
if (WSAGetLastError() == 0)
return true;
return false;
}
SOCKET & InitSocket::GetServerSocket()
{
return m_ServerSocket;
}
// main.cpp
// WSAEventSelect.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "InitSocket.h"
#include <Windows.h>
using namespace std;
int main()
{
InitSocket initSocket;
initSocket.StartUp();
if (initSocket.IsStartUp())
{
bool use = true;
initSocket.SetWhetherUseAddrAny(use);
if (initSocket.Bind())
{
if (initSocket.Listen())
{
SOCKET serverSocket = initSocket.GetServerSocket();
// 1.创建事件
HANDLE hEventListen = WSACreateEvent();
// 2.声明事件对象数组
WSAEVENT eventArr[WSA_MAXIMUM_WAIT_EVENTS];
// 3.声明和事件相关的套接字数组
SOCKET socketArr[WSA_MAXIMUM_WAIT_EVENTS];
// 4.时间对象计数器
int nEventCnt(0);
WSAEventSelect(serverSocket, hEventListen, FD_ACCEPT | FD_CLOSE);
eventArr[0] = hEventListen;
socketArr[0] = serverSocket;
++nEventCnt;
while (true)
{
// 得到受信号的事件对象的下标 这里不等待所有事件受信号,等待单个,时间无限大
int SingalEventIndex = ::WSAWaitForMultipleEvents(nEventCnt, eventArr, false, WSA_INFINITE,false);
int errorCode = WSAGetLastError();
if (SingalEventIndex == WSA_WAIT_IO_COMPLETION || SingalEventIndex == WSA_WAIT_TIMEOUT)
{
// 执行失败或者超时
break;
}
// 得到受信号对象在数组中的下标
int SingalEventArrIndex = SingalEventIndex - WSA_WAIT_EVENT_0;
// 取出和该事件对象关联的套接字
SOCKET SignalSocket = socketArr[SingalEventArrIndex];
WSANETWORKEVENTS netWorkEvents; // 发生的网络事件
::WSAEnumNetworkEvents(SignalSocket, eventArr[SingalEventArrIndex], &netWorkEvents);
// 如果是有新的连接并且没有出错
if ((netWorkEvents.lNetworkEvents & FD_ACCEPT) && netWorkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)
{
if (nEventCnt >= WSA_MAXIMUM_WAIT_EVENTS)
{
// 超过了64 个事件对象
continue;
}
sockaddr_in clientInfo;
int len = sizeof(clientInfo);
SOCKET clientSocket = ::accept(SignalSocket, (sockaddr*)&clientInfo, &len);
if (WSAGetLastError() == 0)
{
// 新的连接成功 为该客户端套接字创建新的事件对象
WSAEVENT clientEvent = ::WSACreateEvent();
// 把新的事件对象加入
::WSAEventSelect(clientSocket, clientEvent, FD_READ | FD_WRITE | FD_CLOSE);
eventArr[nEventCnt] = clientEvent;
socketArr[nEventCnt++] = clientSocket;
cout << "收到来自 " << inet_ntoa(clientInfo.sin_addr) << " 的连接" << endl;//.S_un.S_addr
}
}
else if (netWorkEvents.lNetworkEvents & FD_READ && netWorkEvents.iErrorCode[FD_READ_BIT] == 0)
{
char Buf[512];
memset(Buf, 0, sizeof(char) * 512);
int nRecv = ::recv(SignalSocket, Buf, 512, 0);
if (nRecv > 0)
{
cout << "受到客户端信息: " << Buf << endl;
}
}
else if (netWorkEvents.lNetworkEvents & FD_CLOSE && netWorkEvents.iErrorCode[FD_CLOSE_BIT] == 0)
{
closesocket(socketArr[SingalEventArrIndex]);
for (int i = SingalEventArrIndex; i < nEventCnt; i++)
{
eventArr[i] = eventArr[i+1];
socketArr[i] = socketArr[i+1];
}
}
}
}
}
}
return 0;
}
// TCP客户端测试
// Client.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <WinSock2.h>
int main()
{
WSADATA wsa;
::WSAStartup(MAKEWORD(2, 2), &wsa);
if (WSAGetLastError() == 0)
{
SOCKET serverSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serverInfo;
serverInfo.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
serverInfo.sin_port = htons(6666);
serverInfo.sin_family = AF_INET;
::connect(serverSocket, (const sockaddr*)&serverInfo, sizeof(serverInfo));
int errCode = WSAGetLastError();
::send(serverSocket, "hello world", 11, 0);
errCode = WSAGetLastError();
{
getchar();
}
}
return 0;
}