#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "winsock2.h"
#include <string>
//#include <winsock2.h>
#include <iostream>
#include <mswsock.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"Mswsock.lib")
using namespace std;
struct fd_es_set //事件模型
{
UINT count;
SOCKET socketServer;
HANDLE event;
};
#include "main.h"
fd_es_set allsock;
LONG64 write_error()
{
return 1;
}
void clear()
{
/*释放整个结构体,可能有些事件和socket已经被释放过了,不影响*/
{
//释放stocket
closesocket(allsock.socketServer);
//关闭事件对象
WSACloseEvent(allsock.event);
}
//清理网络库
WSACleanup();
}
int create(const char* ServerIpAdress)
{
/*接收信息,主要是高低版本信息*/
WSADATA wsaData;
/* 使用Windef.h中声明的MAKEWORD(低字节、高字节)宏 */
WORD wVersionRequested = MAKEWORD(2, 2);
/*启用网络链接库,调用的封装库命令*/
if (0 != WSAStartup(wVersionRequested, &wsaData))
{
write_error();
return -1;
}
/*确认WinSock DLL支持2.2*/
/*请注意,如果DLL支持更高版本*/
/*除了2.2之外,它还将返回*/
/*wVersion中的2.2,因为这是我们*/
/*请求*/
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
write_error();
//清理网络库
WSACleanup();
return -1;
}
//创建绑定到特定传输服务提供程序的套接字。 创建网络类型 tcp或者upd
allsock.socketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (INVALID_SOCKET == allsock.socketServer)
{
write_error();
//清理网络库
WSACleanup();
return -1;
}
//设置sockaddr结构
sockaddr_in saServer;
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = INADDR_ANY;// inet_addr(ServerIpAdress);
saServer.sin_port = htons(10000);//ntohs(saServer.sin_port)改回去
//使用绑定侦听套接字 绑定IP和端口
//sockaddr结构中的信息
if (SOCKET_ERROR == bind(allsock.socketServer, (SOCKADDR*)&saServer, sizeof(saServer)))
{
string ret = to_string(WSAGetLastError());
MessageBoxA(0, ret.c_str(), "error_bind", 0);
//释放stocket
closesocket(allsock.socketServer);
//清理网络库
WSACleanup();
return -1;
}
/*创建一个套接字 事件*/
allsock.event = WSACreateEvent();
if (WSA_INVALID_EVENT == allsock.event)
{
string ret = to_string(WSAGetLastError());
MessageBoxA(0, "error_WSACreateEventServer", ret.c_str(), 0);
//释放stocket
closesocket(allsock.socketServer);
//清理网络库
WSACleanup();
return -1;
}
/*将服务器socket和事件绑定*/
if (SOCKET_ERROR == WSAEventSelect(allsock.socketServer, allsock.event, FD_READ | FD_WRITE))
{
string ret = to_string(WSAGetLastError());
MessageBoxA(0, "error_WSAEventSelecttServer", ret.c_str(), 0);
//释放stocket
closesocket(allsock.socketServer);
//清理网络库
WSACleanup();
return -1;
}
while (1)
{
Sleep(3);
{
DWORD RET = 0;
/*等待事件:有事件产生后返回对应事件的下标*/
RET = WSAWaitForMultipleEvents(1, &allsock.event, false, WSA_INFINITE, false);
/*返回错误*/
if (WSA_WAIT_FAILED == RET)
{
string ret = to_string(WSAGetLastError());
MessageBoxA(0, "error_WSAWaitForMultipleEvents", ret.c_str(), 0);
continue;
}
/*等待超时检测*/
/*枚举事件:获取事件类型,并重置其的信号*/
WSANETWORKEVENTS GetlpNetworkEvents;
if (SOCKET_ERROR == WSAEnumNetworkEvents(allsock.socketServer, allsock.event, &GetlpNetworkEvents))
{
string ret = to_string(WSAGetLastError());
MessageBoxA(0, "error_WSAEnumNetworkEvents", ret.c_str(), 0);
continue;
}
/*********FD_READ 可能是组合指令,故需要 & 判断*/
if (GetlpNetworkEvents.lNetworkEvents & FD_READ)
{
if (0 == GetlpNetworkEvents.iErrorCode[FD_READ_BIT])
{//正常处理
sockaddr_in ClientMsg = { 0 };
int ClientMsg_size = sizeof(ClientMsg);
char buff[548];
memset(buff, 0, sizeof(buff));
if (SOCKET_ERROR == recvfrom(allsock.socketServer, buff, sizeof(buff), 0, (sockaddr*)&ClientMsg, &ClientMsg_size))
{
continue;
}
printf("ClientIp:%d.%d.%d.%d:%d \n Buff:%s\n\n",
ClientMsg.sin_addr.S_un.S_un_b.s_b1,
ClientMsg.sin_addr.S_un.S_un_b.s_b2,
ClientMsg.sin_addr.S_un.S_un_b.s_b3,
ClientMsg.sin_addr.S_un.S_un_b.s_b4,
ntohs(ClientMsg.sin_port),
buff);
char sendbuff[548] = "get";
if (SOCKET_ERROR == sendto(allsock.socketServer, sendbuff, strlen(sendbuff), 0, (sockaddr*)&ClientMsg, sizeof(ClientMsg)))
{
continue;
}
}
else
{
continue;
}
}
}
}
clear();
}
BOOL WINAPI HANDLER_ROUTINE(_In_ DWORD CtrlType)
{
switch (CtrlType)
{
case CTRL_CLOSE_EVENT:
{
clear();
}
default:
break;
}
return true;
}
int main()
{
//创建个回调监视控制台关闭
SetConsoleCtrlHandler(HANDLER_ROUTINE, true);
create("0");
return 1;
}
由于UDP是无绑定通信故没有 ACCEPT和CLOSE,比较简单