Witam, chciałbym zaprezentować klasę którą napisałem do swojego projektu, miała ona maksymalnie ułatwić korzystanie z interfejsu sieciowego. Pomyślałem że ten kawałek kodu może się komuś przydać, a jednocześnie mógłbym z waszą pomocą go udoskonalić. Zaznaczam że jestem w miarę świeżym programistą, więc kod może zawierać trochę(dużo) głupich błędów, coś pewnie można by zrobić lepiej etc.
PS. Klasę oddaje na licencji public domain (ale i tak miło by o mnie wspomnieć w swoim projekcie)
WinSockClass.hpp:
#ifndef WINSOCKCLASS_HPP_INCLUDED
#define WINSOCKCLASS_HPP_INCLUDED
#include <ws2tcpip.h>
#define DEFAULT_BUFLEN 512
class WSA
{
private:
WSADATA wsaData;
char *ip;
int iSendResult;
int iResult;
char *port;
bool UDP;
sockaddr_in RecvAddr;
void Initialize();
public:
int temp;
int Destiny; // 0 - Client 1-Server
int error;
struct addrinfo *result = NULL, *ptr = NULL, hints;
sockaddr_in SendAddr;
SOCKET ClientSocket;
char recvbuf[DEFAULT_BUFLEN];
WSA(char* IP, int Dest = 0, char* Port = "27015");
//Client
void ConnectToSocket(SOCKET Socket, bool UDPConn);
//Client_End
//Server
void Bind(SOCKET Socket, bool UDPConn);
void Listen(SOCKET Socket, bool UDPConn);
void AcceptClient(SOCKET Socket, bool UDPConn);
//Server_End
//Both
SOCKET CreateSocket(bool UDPConn);
void Send(SOCKET Socket, char *sendbuf = "This is test", bool UDPConn = false);
char* Recv(SOCKET Socket, bool UDPConn);
void Shutdown(SOCKET Socket);
//Both_End
};
#endif // WINSOCKCLASS_HPP_INCLUDED
WinSockClass.cpp:
#define _WIN32_WINNT 0x501
#include "WinSockClass.hpp"
#include <iostream>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#define DEFAULT_BUFLEN 512
#define SERVER "192.168.100.255"
WSA::WSA(char* IP, int Dest, char* Port)
{
error = 0;
//Socket = INVALID_SOCKET;
ClientSocket = INVALID_SOCKET;
Destiny = Dest;
ip = IP;
port = Port;
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(atoi(Port));
RecvAddr.sin_addr.s_addr = INADDR_ANY;
SendAddr.sin_family = AF_INET;
SendAddr.sin_port = htons(atoi(Port));
SendAddr.sin_addr.S_un.S_addr = inet_addr(ip);
//cout << argv[1] << endl;
Initialize();
}
void WSA::Initialize()
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
error = 1;
return;
}
//CreateSocket();
}
SOCKET WSA::CreateSocket(bool UDPConn)
{
UDP = UDPConn;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
SOCKET Socket = INVALID_SOCKET;
if (!UDPConn)
{
if (Destiny == 0)
{
hints.ai_family = AF_UNSPEC;
iResult = getaddrinfo(ip, port, &hints, &result);
}
else
{
hints.ai_family = AF_INET;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo(NULL, port, &hints, &result);
}
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
error = 2;
return Socket;
}
}
// Attempt to connect to the first address returned by
// the call to getaddrinfo
if (!UDPConn)
{
if(Destiny == 0)
{
ptr=result;
Socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
}
else
{
Socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
}
}
else
{
if (Destiny == 0)
{
Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
else
{
Socket = socket(AF_INET, SOCK_DGRAM, 0);
}
}
if (Socket == INVALID_SOCKET) {
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
freeaddrinfo(result);
WSACleanup();
error = 3;
return Socket;
}
return Socket;
}
void WSA::ConnectToSocket(SOCKET Socket, bool UDPConn)
{
// Connect to server.
iResult = connect( Socket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(Socket);
Socket = INVALID_SOCKET;
}
// Should really try the next address returned by getaddrinfo
// if the connect call failed
// But for this simple example we just free the resources
// returned by getaddrinfo and print an error message
freeaddrinfo(result);
if (Socket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
error = 4;
return;
}
return;
}
void WSA::Send(SOCKET Socket, char *sendbuf, bool UDPConn)
{
// Send an initial buffer
if(!UDPConn)
{
if (Destiny == 0)
{
iResult = send(Socket, sendbuf, (int) strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(Socket);
WSACleanup();
error = 5;
return;
}
}
else
{
iSendResult = send(ClientSocket, sendbuf, (int) strlen(sendbuf), 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
error = 10;
return;
}
}
}
else
{
iResult = sendto(Socket, sendbuf,strlen(sendbuf), 0, (SOCKADDR *) & SendAddr, sizeof(SendAddr));
if (iResult == SOCKET_ERROR) {
wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
closesocket(Socket);
WSACleanup();
error = 5;
return;
}
}
std::cout << "Bytes Sent: " << iResult << std::endl;
//Recv();
return;
}
char* WSA::Recv(SOCKET Socket, bool UDPConn)
{
int SendAddrSize = sizeof (SendAddr);//Only for UDP
memset(recvbuf, 0, 511);
do {
if(!UDPConn)
{
if(Destiny == 0)
{
iResult = recv(Socket, recvbuf, DEFAULT_BUFLEN, 0);
}
else
{
iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
}
}
else
{
iResult = recvfrom(Socket, recvbuf, DEFAULT_BUFLEN, 0,(SOCKADDR *) & SendAddr, &SendAddrSize);
}
if (iResult > 0)
{
temp = iResult;
printf("Bytes received: %d\n", iResult);
break;
}
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult > 0);
return recvbuf;
}
void WSA::Shutdown(SOCKET Socket)
{
// shutdown the send half of the connection since no more data will be sent
if(Destiny == 0)
{
iResult = shutdown(Socket, SD_SEND);
}
else
{
iResult = shutdown(ClientSocket, SD_SEND);
if(UDP)
iResult = shutdown(Socket, SD_SEND);
}
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
error = 6;
return;
}
closesocket(Socket);
closesocket(ClientSocket);
//WSACleanup();
}
void WSA::Bind(SOCKET Socket, bool UDPConn)
{
if(!UDPConn)
{
iResult = bind(Socket, result->ai_addr, (int)result->ai_addrlen);
}
else
{
iResult = bind(Socket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
}
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(Socket);
WSACleanup();
error = 7;
return ;
}
freeaddrinfo(result);
return;
}
void WSA::Listen(SOCKET Socket, bool UDPConn)
{
if ( listen( Socket, SOMAXCONN ) == SOCKET_ERROR ) {
std::cout << "Listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(Socket);
WSACleanup();
error = 8;
return;
}
return;
}
void WSA::AcceptClient(SOCKET Socket, bool UDPConn)
{
// Accept a client socket
ClientSocket = accept(Socket, NULL, NULL);
if (Socket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(Socket);
WSACleanup();
error = 9;
return;
}
return;
}