/**************客户端代码 *******************/
#include <iostream>
#include <WS2tcpip.h>
#include <WinSock2.H>
#pragma comment(lib, "ws2_32.lib")
#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 8000
#define SOCKET_NUM 1 /// 客户端socket的个数,修改该值可以改变连接到服务器的客户端个数
#pragma pack(push,1)
struct MyStruct
{
unsigned int a;
unsigned int b;
};
#pragma pack()
int main()
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) return 1;
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup();
std::cout << "WSAStartup() error." << std::endl;
return -1;
}
SOCKET allSocketClients[SOCKET_NUM];
for (int i = 0; i < SOCKET_NUM; i ++)
{
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socketClient == INVALID_SOCKET)
{
WSACleanup();
std::cout << "socket() error." << std::endl;
return -1;
}
allSocketClients[i] = socketClient;
}
SOCKADDR_IN server;
memset(&server, 0, sizeof(SOCKADDR_IN));
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
inet_pton(server.sin_family, SERVER_ADDRESS, &server.sin_addr);
for (int i = 0; i < SOCKET_NUM; i++)
{
SOCKET socketClient = allSocketClients[i];
err = connect(socketClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));
if (err == SOCKET_ERROR)
{
std::cout << "connect() error." << std::endl;
closesocket(socketClient);
WSACleanup();
return -1;
}
}
for (int i = 0; i < SOCKET_NUM; i++)
{
SOCKET socketClient = allSocketClients[i];
MyStruct st;
st.a =200;
st.b =300;
char message[100] = { 0 };
memcpy(message,&st,sizeof(st));
int iSendData = send(socketClient, message, sizeof(st), 0);
}
for (int i = 0; i < SOCKET_NUM; i++)
{
SOCKET socketClient = allSocketClients[i];
closesocket(socketClient);
}
WSACleanup();
return 0;
}
/***************服务端代码*************************
#include <iostream>
#include <stdio.h>
#include "TcpBase.h"
#pragma pack(push,1)
struct MyStruct
{
unsigned int a;
unsigned int b;
};
#pragma pack()
class TcpSer:public TcpBase
{
public:
TcpSer()
:_fp(NULL)
{
bufRecv = new char[100];
memset(bufRecv,0,100);
}
virtual~TcpSer()
{
delete []bufRecv;
bufRecv = NULL;
}
static unsigned long __stdcall RecvSocket(void* ptr)
{
TcpSer* ptrSer = (TcpSer* )(ptr);
struct timeval tv = {2, 0};
memset(&ptrSer->allSockSetT,0,sizeof(ptrSer->allSockSetT));
FD_SET(ptrSer->_sSocket, &ptrSer->allSockSetT); // 将socketListen加入套接字集合中
while (true)
{
fd_set fdOld = ptrSer->allSockSetT;//此地方不写的话,会造成 select错误
int result = select(0, &fdOld, NULL, NULL, &tv);
if (result == SOCKET_ERROR)
{
std::cout << "listen() error." << std::endl;
break;
}
if(result == 0)
{
continue;
}
if(result>0)
{
for(int i = 0;i < ptrSer->allSockSetT.fd_count; i++)
{
if (FD_ISSET(ptrSer->allSockSetT.fd_array[i],&fdOld))
{
//如果socket是服务器,则接收连接
if (ptrSer->allSockSetT.fd_array[i] == ptrSer->_sSocket)
{
SOCKET clientSocket = ptrSer->Accpect();
if (clientSocket == INVALID_SOCKET)
{
std::cout << "accept() error." << std::endl;
break;
}
FD_SET(clientSocket, &ptrSer->allSockSetT); /// 将新创建的套接字加入到集合中
std::cout << "], 目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl;
}
else //非服务器,接收数据(因为fd是读数据集)
{
SOCKET socket = ptrSer->allSockSetT.fd_array[i];
sockaddr_in clientAddr;
int len = sizeof(clientAddr);
getpeername(socket, (struct sockaddr *)&clientAddr, &len);
char ipAddress[16] = { 0 };
inet_ntop(AF_INET, &clientAddr, ipAddress, 16);
result = ptrSer->RecvData(socket,( unsigned char*)ptrSer->bufRecv,100);
if (result == SOCKET_ERROR)
{
DWORD err = WSAGetLastError();
if (err == WSAECONNRESET) /// 客户端的socket没有被正常关闭,即没有调用closesocket
{
std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port) << "]被强行关闭, ";
}
else
{
std::cout << "recv() error," << std::endl;
}
closesocket(socket);
FD_CLR(socket, &ptrSer->allSockSetT);
std::cout << "目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl;
break;
}
else if (result == 0) /// 客户端的socket调用closesocket正常关闭
{
closesocket(socket);
FD_CLR(socket, &ptrSer->allSockSetT);
if(ptrSer->allSockSetT.fd_count >0)
{
std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)
<< "]已经退出,目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl;
}
else
{
std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)
<< "]已经退出,目前客户端的数量为:" << ptrSer->allSockSetT.fd_count << std::endl;
}
break;
}
int dataSize = ptrSer->SendData(socket,(const unsigned char*)ptrSer->bufRecv,result);
MyStruct *ptr =(MyStruct*)(ptrSer->bufRecv);
ptrSer->bufRecv[result] = '\0';
std::cout << "来自客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)
<< "]的消息:" << ptr->a <<" "<<ptr->b<<std::endl;
}
}
}
}
Sleep(200);
}
return 0;
}
private:
fd_set allSockSetT;
char *bufRecv;
FILE *_fp;
};
int main()
{
/// 初始化socket
unsigned short iPort = 8000;
TcpSer ser;
ser.BindSocket(iPort);
ser.ListenSocket(200);
void *pThread = CreateThread(NULL,0,TcpSer::RecvSocket,&ser,0,NULL);
WaitForSingleObject(pThread,0xFFFFFFFF);
//for (u_int i = 0; i < allSockSetT.fd_count; ++i)
//{
// SOCKET socket = allSockSetT.fd_array[i];
// closesocket(socket);
//}
WSACleanup();
return 0;
}