// IPv6.h: 头文件,这里使用到了套接字中的“select I/O模型”
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <tpipv6.h> // IPv6 头文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")//套接字库文件
#define DEFAULT_PORT "7274" // 默认端口
#define BUFFER_SIZE 64 // 数据缓冲区
class CIPv6
{
public:
// 创建TCP 服务器
int CreateServer(char *Port = DEFAULT_PORT,char *Address = NULL);
void Usage(char *ProgName);//用户信息提示
LPSTR DecodeError(int ErrorCode);//获取错误信息
CIPv6();
virtual ~CIPv6();
};
// IPv61.cpp: CIPv6类的实现 .
// IPv61.cpp: implementation of the CIPv6 class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IPv61.h"
int CIPv6::CreateServer(char *Port, char *Address)
{
char Buffer[BUFFER_SIZE], Hostname[NI_MAXHOST];
int RetVal, FromLen, AmountRead;
SOCKADDR_STORAGE From;
WSADATA wsaData;
ADDRINFO Hints, *AddrInfo;
SOCKET ServSock;
fd_set SockSet;
// 启动Winsock
if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
fprintf(stderr, "WSAStartup failed with error %d: %s\n",
RetVal, DecodeError(RetVal));
WSACleanup();
return -1;
}
if (Port == NULL)
{
Usage("Port Error");
}
memset(&Hints, 0, sizeof(Hints));
Hints.ai_family =AF_INET6;// Family;
Hints.ai_socktype =SOCK_STREAM;
Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
RetVal = getaddrinfo(Address, Port, &Hints, &AddrInfo);
if (RetVal != 0)
{
fprintf(stderr, "getaddrinfo failed with error %d: %s\n", RetVal, gai_strerror(RetVal));
WSACleanup();
return -1;
}
// 创建套接字
ServSock = socket(AddrInfo->ai_family,AddrInfo->ai_socktype, AddrInfo->ai_protocol);
if (ServSock == INVALID_SOCKET)
{
fprintf(stderr, "socket() failed with error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
WSACleanup();
return -1;
}
// 绑定套接字
if (bind(ServSock, AddrInfo->ai_addr, AddrInfo->ai_addrlen) == SOCKET_ERROR)
{
fprintf(stderr,"bind() failed with error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
WSACleanup();
return -1;
}
// 侦听
if (listen(ServSock, 5) == SOCKET_ERROR)
{
fprintf(stderr, "listen() failed with error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
WSACleanup();
return -1;
}
printf("'Listening' on port %s, protocol %s, protocol family %s\n",
Port, \"TCP\",
"PF_INET6");
freeaddrinfo(AddrInfo);
//使用select I/O 模型进行收发
FD_ZERO(&SockSet);
while(1)
{
FromLen = sizeof(From);
if (FD_ISSET(ServSock, &SockSet)) break;
FD_SET(ServSock, &SockSet);
if (select(0, &SockSet, 0, 0, 0) == SOCKET_ERROR)
{
fprintf(stderr, "select() failed with error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
WSACleanup();
return -1;
}
}
if (FD_ISSET(ServSock, &SockSet))
{
FD_CLR(ServSock, &SockSet);
}
//接受一个连接
SOCKET ConnSock;
ConnSock = accept(ServSock, (LPSOCKADDR)&From, &FromLen);
if (ConnSock == INVALID_SOCKET)
{
fprintf(stderr, "accept() failed with error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
WSACleanup();
return -1;
}
if (getnameinfo((LPSOCKADDR)&From, FromLen, Hostname,
sizeof(Hostname), NULL, 0, NI_NUMERICHOST) != 0)
strcpy(Hostname, "<unknown>");
printf("\nAccepted connection from %s\n", Hostname);
while(1)
{
//等待接受数据
AmountRead = recv(ConnSock, Buffer, sizeof(Buffer), 0);
if (AmountRead == SOCKET_ERROR)
{
fprintf(stderr, "recv() failed with error %d: %s\n", WSAGetLastError(), DecodeError(WSAGetLastError()));
closesocket(ConnSock);
break;
}
if (AmountRead == 0) {
printf("Client closed connection\n");
closesocket(ConnSock);
break;
}
printf("Received %d bytes from client: [%.*s]\n",
AmountRead, AmountRead, Buffer);
//进行简单ECHO 回应
printf("Echoing same data back to client\n");
RetVal = send(ConnSock, Buffer, AmountRead, 0);
if (RetVal == SOCKET_ERROR)
{
fprintf(stderr, "send() failed: error %d: %s\n",
WSAGetLastError(), DecodeError(WSAGetLastError()));
closesocket(ConnSock);
break;
}
}
return 0;
}
void CIPv6::Usage(char *ProgName)
{
fprintf(stderr, "\nSimple socket sample server program.\n");
fprintf(stderr, "transport tEither TCP or UDP. (default: %s)\n",
"TCP");
fprintf(stderr, "port\t\tPort on which to bind. (default %s)\n",
DEFAULT_PORT);
fprintf(stderr, "address\tIP address on which to bind.(default: unspecified address)\n");
WSACleanup();
exit(1);
}
LPSTR CIPv6::DecodeError(int ErrorCode)
{
static char Message[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)Message, 1024, NULL);
return Message;
}