restructure and add server/client example
This commit is contained in:
parent
729b475135
commit
ec7b293bd5
@ -21,21 +21,34 @@ ExternalProject_Add(
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
|
||||
|
||||
add_executable(app
|
||||
src/main.cpp
|
||||
src/App.cpp
|
||||
src/DnaStore.cpp
|
||||
src/sys.cpp
|
||||
src/canvas/BackGround.cpp
|
||||
src/canvas/BackGroundColors.cpp
|
||||
src/canvas/Canvas.cpp
|
||||
src/canvas/Circle.cpp
|
||||
src/canvas/Tree.cpp
|
||||
src/values/Dna.cpp
|
||||
src/values/DnaManager.cpp
|
||||
src/values/mrand.cpp
|
||||
app/src/main.cpp
|
||||
app/src/App.cpp
|
||||
app/src/DnaStore.cpp
|
||||
app/src/sys.cpp
|
||||
shared/src/canvas/BackGround.cpp
|
||||
shared/src/canvas/BackGroundColors.cpp
|
||||
shared/src/canvas/Canvas.cpp
|
||||
shared/src/canvas/Circle.cpp
|
||||
shared/src/canvas/Tree.cpp
|
||||
shared/src/values/Dna.cpp
|
||||
shared/src/values/DnaManager.cpp
|
||||
shared/src/values/mrand.cpp
|
||||
)
|
||||
# Add include directories
|
||||
target_include_directories(app PRIVATE inc ${CMAKE_BINARY_DIR}/raylib/include)
|
||||
target_link_libraries(app ${CMAKE_BINARY_DIR}/raylib/lib/libraylib.a)
|
||||
target_include_directories(app PRIVATE app/inc shared/inc ${CMAKE_BINARY_DIR}/raylib/include)
|
||||
target_link_libraries(app ${CMAKE_BINARY_DIR}/raylib/lib/libraylib.a)
|
||||
|
||||
add_executable(server
|
||||
server/src/server.cpp
|
||||
shared/src/TcpSocket.cpp
|
||||
)
|
||||
# Add include directories
|
||||
target_include_directories(server PRIVATE server/inc shared/inc)
|
||||
|
||||
|
||||
add_executable(client
|
||||
server/src/client.cpp
|
||||
shared/src/TcpSocket.cpp
|
||||
)
|
||||
target_include_directories(client PRIVATE server/inc shared/inc)
|
40
server/src/client.cpp
Normal file
40
server/src/client.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "TcpSocket.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
char mes[] = "Hello Server!";
|
||||
|
||||
int main()
|
||||
{
|
||||
int sock = TcpSocket::connectt("localhost", 8888);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
printf("Error %d", sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char tempBuffer[AS_DEFAULT_BUFFER_SIZE + 1];
|
||||
ssize_t messageLength;
|
||||
|
||||
// You should do an input loop, so the program won't terminate immediately
|
||||
string input;
|
||||
getline(cin, input);
|
||||
while (input != "exit")
|
||||
{
|
||||
TcpSocket::sendt(sock, input.data(), input.size());
|
||||
messageLength = TcpSocket::recvt(sock, tempBuffer, AS_DEFAULT_BUFFER_SIZE);
|
||||
if (messageLength <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
tempBuffer[messageLength] = 0;
|
||||
printf("%s\n", tempBuffer);
|
||||
getline(cin, input);
|
||||
}
|
||||
|
||||
TcpSocket::closet(sock);
|
||||
|
||||
return 0;
|
||||
}
|
34
server/src/server.cpp
Normal file
34
server/src/server.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "TcpSocket.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// use pthread rw_lock to lock db so you can safy clone .db file
|
||||
|
||||
int main()
|
||||
{
|
||||
// When a new client connected:
|
||||
TcpSocket::OnNewConnectionCallBack onNewConnection = [](int sock, sockaddr_in newSocketInfo)
|
||||
{
|
||||
std::cout << "new User" << std::endl;
|
||||
char tempBuffer[AS_DEFAULT_BUFFER_SIZE + 1];
|
||||
ssize_t messageLength;
|
||||
while ((messageLength = TcpSocket::recvt(sock, tempBuffer, AS_DEFAULT_BUFFER_SIZE)) > 0)
|
||||
{
|
||||
tempBuffer[messageLength] = '\0';
|
||||
TcpSocket::sendt(sock, tempBuffer, messageLength);
|
||||
}
|
||||
std::cout << "del USER" << std::endl;
|
||||
TcpSocket::closet(sock);
|
||||
};
|
||||
|
||||
// Bind the server to a port.
|
||||
int err = TcpSocket::listent("0.0.0.0", 8888, onNewConnection);
|
||||
if (err < 0)
|
||||
{
|
||||
printf("ERROR %d", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
28
shared/inc/TcpSocket.hpp
Normal file
28
shared/inc/TcpSocket.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define AS_DEFAULT_BUFFER_SIZE 0x1000 /*4096 bytes*/
|
||||
|
||||
namespace TcpSocket
|
||||
{
|
||||
|
||||
void setTimeout(int seconds, int sock);
|
||||
|
||||
ssize_t sendt(int sock, const void *bytes, size_t byteslength);
|
||||
|
||||
ssize_t recvt(int sock, void *bytes, size_t byteslength);
|
||||
|
||||
void closet(int sock);
|
||||
|
||||
std::string remoteAddress(sockaddr_in &address);
|
||||
|
||||
int remotePort(sockaddr_in &address);
|
||||
int connectt(const char *host, uint16_t port);
|
||||
|
||||
typedef std::function<void(int sock, sockaddr_in newSocketInfo)> OnNewConnectionCallBack;
|
||||
int listent(const char *host, uint16_t port, OnNewConnectionCallBack callback);
|
||||
|
||||
} // namespace TcpSocket
|
169
shared/src/TcpSocket.cpp
Normal file
169
shared/src/TcpSocket.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
|
||||
namespace TcpSocket
|
||||
{
|
||||
|
||||
void setTimeout(int seconds, int sock)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
|
||||
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
|
||||
}
|
||||
|
||||
ssize_t sendt(int sock, const void *bytes, size_t byteslength) { return send(sock, bytes, byteslength, 0); }
|
||||
|
||||
ssize_t recvt(int sock, void *bytes, size_t byteslength) { return recv(sock, bytes, byteslength, 0); }
|
||||
|
||||
void closet(int sock)
|
||||
{
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
}
|
||||
|
||||
std::string remoteAddress(sockaddr_in &address)
|
||||
{
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(address.sin_addr), ip, INET_ADDRSTRLEN);
|
||||
|
||||
return std::string(ip);
|
||||
}
|
||||
|
||||
int remotePort(sockaddr_in &address) { return ntohs(address.sin_port); }
|
||||
|
||||
int connectt(const char *host, uint16_t port)
|
||||
{
|
||||
struct addrinfo hints, *res, *it;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// Get address info from DNS
|
||||
int status = getaddrinfo(host, NULL, &hints, &res);
|
||||
if (status != 0)
|
||||
{
|
||||
// onError(errno, "Invalid address." + std::string(gai_strerror(status)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_in address;
|
||||
for (it = res; it != NULL; it = it->ai_next)
|
||||
{
|
||||
if (it->ai_family == AF_INET)
|
||||
{ // IPv4
|
||||
memcpy((void *)(&address), (void *)it->ai_addr, sizeof(sockaddr_in));
|
||||
break; // for now, just get the first ip (ipv4).
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock == -1)
|
||||
{
|
||||
// onError(errno, "Socket creating error.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
// setTimeout(5, sock);
|
||||
|
||||
// Try to connect.
|
||||
status = connect(sock, (const sockaddr *)&address, sizeof(sockaddr_in));
|
||||
if (status == -1)
|
||||
{
|
||||
// onError(errno, "Connection failed to the host.");
|
||||
close(sock);
|
||||
return -3;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
typedef std::function<void(int sock, sockaddr_in newSocketInfo)> OnNewConnectionCallBack;
|
||||
|
||||
int listent(const char *host, uint16_t port, OnNewConnectionCallBack callback)
|
||||
{
|
||||
sockaddr_in address;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock == -1)
|
||||
{
|
||||
// onError(errno, "Socket creating error.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(int));
|
||||
|
||||
int status = inet_pton(AF_INET, host, &address.sin_addr);
|
||||
switch (status)
|
||||
{
|
||||
case -1:
|
||||
close(sock);
|
||||
// onError(errno, "Invalid address. Address type not supported.");
|
||||
return -2;
|
||||
case 0:
|
||||
close(sock);
|
||||
// onError(errno, "AF_INET is not supported. Please send message to developer.");
|
||||
return -3;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (bind(sock, (const sockaddr *)&address, sizeof(address)) == -1)
|
||||
{
|
||||
// onError(errno, "Cannot bind the socket.");
|
||||
close(sock);
|
||||
return -4;
|
||||
}
|
||||
if (listen(sock, 20) == -1)
|
||||
{
|
||||
// onError(errno, "Error: Server can't listen the socket.");
|
||||
close(sock);
|
||||
return -5;
|
||||
}
|
||||
|
||||
sockaddr_in newSocketInfo;
|
||||
socklen_t newSocketInfoLength = sizeof(newSocketInfo);
|
||||
|
||||
int newSocketFileDescriptor = -1;
|
||||
while (true)
|
||||
{
|
||||
newSocketFileDescriptor = accept(sock, (sockaddr *)&newSocketInfo, &newSocketInfoLength);
|
||||
if (newSocketFileDescriptor == -1)
|
||||
{
|
||||
if (errno == EBADF || errno == EINVAL)
|
||||
return -6;
|
||||
|
||||
return -7;
|
||||
}
|
||||
|
||||
std::thread t(callback, newSocketFileDescriptor, newSocketInfo);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user