wintendo entertainment socket
This commit is contained in:
parent
698a12ddb4
commit
c079f49be6
4 changed files with 283 additions and 15 deletions
|
@ -6,7 +6,18 @@ file(GLOB_RECURSE server_src
|
||||||
"src/*.cpp"
|
"src/*.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(server ${server_src})
|
add_executable(server ${server_src})
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
target_link_libraries(server pthread nsl resolv)
|
||||||
|
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
target_link_libraries(server wsock32 ws2_32)
|
||||||
|
else()
|
||||||
|
target_link_libraries(server pthread socket nsl resolv)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS server RUNTIME DESTINATION bin)
|
install(TARGETS server RUNTIME DESTINATION bin)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "utils/net.hpp"
|
#include "utils/net.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
#include "sock/tcpsock.hpp"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
//auto sock = sosc::TcpClient();
|
//auto sock = sosc::TcpClient();
|
||||||
|
@ -14,14 +15,21 @@ int main(int argc, char **argv) {
|
||||||
std::cout << i << std::endl;
|
std::cout << i << std::endl;
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
uint32_t test = 0xDEADBEEF;
|
sosc::TcpClient client;
|
||||||
std::string net = HTONUL(test);
|
sosc::TcpServer server;
|
||||||
test = NTOHUL(net);
|
|
||||||
|
|
||||||
sosc::net::IpAddress ip1, ip2;
|
server.Listen(1111);
|
||||||
ip1.Parse("::*:FE:EF:F**F");
|
server.Accept(&client);
|
||||||
ip2.Parse("::ABCD:F*:*:F00F");
|
|
||||||
bool same = ip1 == ip2;
|
client.Send("test");
|
||||||
|
std::string got;
|
||||||
|
|
||||||
|
while(client.IsOpen()) {
|
||||||
|
int length = client.Recv(&got);
|
||||||
|
|
||||||
|
if(length > 0)
|
||||||
|
std::cout << got << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
#define SOSC_TCPSOCK_H
|
#define SOSC_TCPSOCK_H
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT _WIN32_WINNT_WIN8
|
||||||
|
#endif
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
@ -21,11 +26,13 @@
|
||||||
#define SOSC_ADDR_T struct sockaddr_in
|
#define SOSC_ADDR_T struct sockaddr_in
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <string>
|
||||||
#include "../utils/net.hpp"
|
#include "../utils/net.hpp"
|
||||||
|
#include "../utils/string.hpp"
|
||||||
|
|
||||||
#define SOSC_TCP_BUFLEN 2048
|
#define SOSC_TCP_BUFLEN 2048
|
||||||
|
|
||||||
|
@ -33,11 +40,26 @@ namespace sosc {
|
||||||
class TcpClient {
|
class TcpClient {
|
||||||
public:
|
public:
|
||||||
TcpClient();
|
TcpClient();
|
||||||
bool Init(std::string host, std::uint16_t port);
|
bool Open(std::string host, std::uint16_t port);
|
||||||
|
|
||||||
|
int Recv(std::string* str, bool append = false);
|
||||||
|
int Send(const std::string& str);
|
||||||
|
|
||||||
|
bool IsDataReady();
|
||||||
|
inline bool IsOpen() const {
|
||||||
|
// TODO consider changing this
|
||||||
|
return this->sock_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline net::IpAddress GetIpAddress() const {
|
||||||
|
return this->ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close();
|
||||||
~TcpClient();
|
~TcpClient();
|
||||||
private:
|
private:
|
||||||
bool Init(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len);
|
void Open(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len);
|
||||||
|
void SetBlocking(bool will_block);
|
||||||
|
|
||||||
SOSC_SOCK_T sock;
|
SOSC_SOCK_T sock;
|
||||||
bool sock_open;
|
bool sock_open;
|
||||||
|
@ -54,10 +76,15 @@ private:
|
||||||
class TcpServer {
|
class TcpServer {
|
||||||
public:
|
public:
|
||||||
TcpServer();
|
TcpServer();
|
||||||
|
bool Listen(uint16_t port);
|
||||||
|
|
||||||
|
int Accept(TcpClient* client);
|
||||||
|
|
||||||
|
void Close();
|
||||||
~TcpServer();
|
~TcpServer();
|
||||||
private:
|
private:
|
||||||
SOSC_SOCK_T sock;
|
SOSC_SOCK_T sock;
|
||||||
|
bool sock_open;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,172 @@
|
||||||
#include "tcpsock.hpp"
|
#include "tcpsock.hpp"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
void init_wsa() {
|
||||||
|
static bool is_inited = false;
|
||||||
|
if(is_inited) return;
|
||||||
|
|
||||||
|
WSADATA wdata;
|
||||||
|
if(WSAStartup(MAKEWORD(2, 2), &wdata) != 0)
|
||||||
|
exit(-1);
|
||||||
|
|
||||||
|
is_inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* BEGIN TCPCLIENT CODE */
|
/* BEGIN TCPCLIENT CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
||||||
sosc::TcpClient::TcpClient() {
|
sosc::TcpClient::TcpClient() {
|
||||||
|
init_wsa();
|
||||||
this->sock_open = false;
|
this->sock_open = false;
|
||||||
this->addr_len = -1;
|
this->addr_len = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::TcpClient::Init(std::string host, std::uint16_t port) {
|
bool sosc::TcpClient::Open(std::string host, std::uint16_t port) {
|
||||||
if(this->sock_open)
|
if(this->sock_open)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct addrinfo hints, *result, *ptr;
|
struct addrinfo hints, *results, *ptr;
|
||||||
|
ZeroMemory(&hints, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
if(getaddrinfo(host.c_str(), TOSTR(port).c_str(), &hints, &results) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(ptr = results; ptr != NULL; ptr = ptr->ai_next) {
|
||||||
|
this->sock = socket(ptr->ai_family,
|
||||||
|
ptr->ai_socktype, ptr->ai_protocol);
|
||||||
|
|
||||||
|
if(this->sock == INVALID_SOCKET) {
|
||||||
|
freeaddrinfo(results);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(connect(this->sock, ptr->ai_addr,
|
||||||
|
(int)ptr->ai_addrlen) != SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(this->sock);
|
||||||
|
this->sock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(results);
|
||||||
|
if(this->sock == INVALID_SOCKET)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->ip = net::IpAddress();
|
||||||
|
this->sock_open = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sosc::TcpClient::Open
|
||||||
|
(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len)
|
||||||
|
{
|
||||||
|
if(this->sock_open)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->sock = sock;
|
||||||
|
this->sock_open = true;
|
||||||
|
|
||||||
|
this->addr = addr;
|
||||||
|
this->addr_len = addr_len;
|
||||||
|
|
||||||
|
char buffer[128];
|
||||||
|
inet_ntop(addr.sin_family, (PVOID)&addr.sin_addr, buffer, 128);
|
||||||
|
this->ip.Parse(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sosc::TcpClient::Recv(std::string* str, bool append) {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int total_length = 0;
|
||||||
|
bool first_recv = true;
|
||||||
|
while(this->IsDataReady()) {
|
||||||
|
int length = recv(this->sock, this->buffer, SOSC_TCP_BUFLEN, 0);
|
||||||
|
if(length <= 0) {
|
||||||
|
this->Close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(first_recv && !append)
|
||||||
|
*str = std::string(this->buffer, length);
|
||||||
|
else
|
||||||
|
*str += std::string(this->buffer, length);
|
||||||
|
|
||||||
|
total_length += length;
|
||||||
|
first_recv = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sosc::TcpClient::Send(const std::string& str) {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
std::string::size_type total_sent = 0;
|
||||||
|
while(total_sent < str.length()) {
|
||||||
|
int sent = total_sent == 0
|
||||||
|
? send(this->sock, str.c_str(), str.length(), 0)
|
||||||
|
: send(this->sock, str.substr(total_sent).c_str(),
|
||||||
|
str.length() - total_sent, 0);
|
||||||
|
|
||||||
|
if(sent == SOCKET_ERROR) {
|
||||||
|
this->Close();
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
total_sent += sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::TcpClient::IsDataReady() {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->SetBlocking(false);
|
||||||
|
int check = recv(this->sock, this->buffer, 1, MSG_PEEK),
|
||||||
|
error = WSAGetLastError();
|
||||||
|
this->SetBlocking(true);
|
||||||
|
|
||||||
|
if(check <= 0) {
|
||||||
|
if(check != 0 && (error == WSAEWOULDBLOCK || error == WSAETIMEDOUT))
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
this->Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::TcpClient::SetBlocking(bool will_block) {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u_long nblock = !will_block;
|
||||||
|
ioctlsocket(this->sock, FIONBIO, &nblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::TcpClient::Close() {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shutdown(this->sock, SD_BOTH);
|
||||||
|
closesocket(this->sock);
|
||||||
|
this->sock_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sosc::TcpClient::~TcpClient() {
|
||||||
|
this->Close();
|
||||||
|
}
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END TCPCLIENT CODE */
|
/* END TCPCLIENT CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
@ -25,7 +174,80 @@ bool sosc::TcpClient::Init(std::string host, std::uint16_t port) {
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
||||||
sosc::TcpServer::TcpServer() {
|
sosc::TcpServer::TcpServer() {
|
||||||
|
init_wsa();
|
||||||
|
this->sock_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::TcpServer::Listen(uint16_t port) {
|
||||||
|
if(this->sock_open)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct addrinfo hints, *result;
|
||||||
|
ZeroMemory(&hints, sizeof(hints));
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
|
||||||
|
if(getaddrinfo(NULL, TOSTR(port).c_str(), &hints, &result) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->sock = socket(result->ai_family,
|
||||||
|
result->ai_socktype, result->ai_protocol);
|
||||||
|
|
||||||
|
if(this->sock == INVALID_SOCKET) {
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bind(this->sock, result->ai_addr,
|
||||||
|
(int)result->ai_addrlen) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
freeaddrinfo(result);
|
||||||
|
closesocket(this->sock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
if(listen(this->sock, SOMAXCONN) == SOCKET_ERROR) {
|
||||||
|
closesocket(this->sock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sock_open = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sosc::TcpServer::Accept(TcpClient* client) {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SOSC_SOCK_T sock;
|
||||||
|
SOSC_ADDR_T addr;
|
||||||
|
int addr_len = sizeof(addr);
|
||||||
|
|
||||||
|
sock = accept(this->sock, (struct sockaddr*)&addr, &addr_len);
|
||||||
|
if(sock == INVALID_SOCKET) {
|
||||||
|
this->Close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->Close();
|
||||||
|
client->Open(sock, addr, addr_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::TcpServer::Close() {
|
||||||
|
if(!this->sock_open)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shutdown(this->sock, SD_BOTH);
|
||||||
|
closesocket(this->sock);
|
||||||
|
this->sock_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sosc::TcpServer::~TcpServer() {
|
||||||
|
this->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
Loading…
Reference in a new issue