cleanup a little bit
This commit is contained in:
@@ -24,53 +24,65 @@ ErrorCode TcpClient::init() {
|
|||||||
logger_->log("TcpClient", LogFlag::Debug, "Initializing TcpClient...");
|
logger_->log("TcpClient", LogFlag::Debug, "Initializing TcpClient...");
|
||||||
|
|
||||||
// keeping everything in here for now
|
// keeping everything in here for now
|
||||||
int socketFd;
|
int socketFd; // file descriptor for the client socket (socket proper is a function)
|
||||||
int sendBytes;
|
int sendBytes;
|
||||||
int receiveBytes;
|
int receiveBytes;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
||||||
struct hostent* host;
|
struct hostent* host; // houses host network info
|
||||||
struct sockaddr_in serverAddress;
|
struct sockaddr_in serverAddress; // ip address of the server socket
|
||||||
struct timeval timestamp;
|
|
||||||
struct timeval timestampEnd;
|
|
||||||
|
|
||||||
|
// parse the hostname string into uint8s
|
||||||
host = gethostbyname(configuration_.hostname.c_str());
|
host = gethostbyname(configuration_.hostname.c_str());
|
||||||
if(host == NULL) {
|
if(host == NULL) {
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Unable to parse hostname.");
|
logger_->log("TcpClient", LogFlag::Debug, "Unable to parse hostname.");
|
||||||
|
close(socketFd); // TODO: probably on a destructor
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create tcp socket
|
||||||
socketFd = socket(AF_INET, SOCK_STREAM, 0);
|
socketFd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if(socketFd < 0) {
|
if(socketFd < 0) {
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Unable to open client socket.");
|
logger_->log("TcpClient", LogFlag::Debug, "Unable to open client socket.");
|
||||||
|
close(socketFd);
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// describe the server address from the hostname and port
|
||||||
|
memset(&serverAddress.sin_zero, 0, sizeof(serverAddress.sin_zero));
|
||||||
serverAddress.sin_family = AF_INET;
|
serverAddress.sin_family = AF_INET;
|
||||||
serverAddress.sin_port = htons(configuration_.port);
|
serverAddress.sin_port = htons(configuration_.port);
|
||||||
serverAddress.sin_addr = *((struct in_addr*)host->h_addr);
|
serverAddress.sin_addr = *((struct in_addr*)host->h_addr);
|
||||||
memset(&serverAddress.sin_zero, 0, sizeof(serverAddress.sin_zero));
|
|
||||||
|
|
||||||
|
// connect to server
|
||||||
if(connect(socketFd, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) {
|
if(connect(socketFd, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) {
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Unable to connect to server.");
|
logger_->log("TcpClient", LogFlag::Debug, "Unable to connect to server.");
|
||||||
|
close(socketFd);
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send data buffer to server
|
||||||
memset(buffer, 0x67, sizeof(buffer));
|
memset(buffer, 0x67, sizeof(buffer));
|
||||||
gettimeofday(×tamp, NULL);
|
|
||||||
|
|
||||||
sendBytes = send(socketFd, buffer, sizeof(buffer), 0);
|
sendBytes = send(socketFd, buffer, sizeof(buffer), 0);
|
||||||
if(sendBytes < 0) {
|
if(sendBytes < 0) {
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Unable to send to server.");
|
logger_->log("TcpClient", LogFlag::Error, "Unable to send to server.");
|
||||||
|
close(socketFd);
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
logger_->log("TcpClient", LogFlag::Debug, "Sent {} bytes to the server.", sendBytes);
|
||||||
|
|
||||||
gettimeofday(×tampEnd, NULL);
|
|
||||||
|
|
||||||
|
// listen for receive from the server
|
||||||
memset(buffer, 0x00, sizeof(buffer));
|
memset(buffer, 0x00, sizeof(buffer));
|
||||||
receiveBytes = recv(socketFd, buffer, sizeof(buffer), 0);
|
receiveBytes = recv(socketFd, buffer, sizeof(buffer), 0); // TODO: this currently blocks forever, add timeout
|
||||||
|
|
||||||
|
// we expect a response based on the server design, something went wrong otherwise
|
||||||
if(receiveBytes < 0) {
|
if(receiveBytes < 0) {
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Unable to receive from server.");
|
logger_->log("TcpClient", LogFlag::Error, "Unable to receive from server.");
|
||||||
|
return ErrorCode::Error;
|
||||||
|
} else if(receiveBytes == 0) {
|
||||||
|
logger_->log("TcpClient", LogFlag::Error, "Server closed the connection during receive.");
|
||||||
|
close(socketFd);
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,69 +24,100 @@ ErrorCode TcpServer::init() {
|
|||||||
logger_->log("TcpServer", LogFlag::Debug, "Initializing TcpServer...");
|
logger_->log("TcpServer", LogFlag::Debug, "Initializing TcpServer...");
|
||||||
|
|
||||||
// keeping everything in here for now
|
// keeping everything in here for now
|
||||||
int socketFd;
|
int serverSocket; // file descriptor for the server's socket
|
||||||
int clientFd;
|
int clientSocket; // file descriptor for the client's socket
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
int receiveBytes;
|
int receiveBytes;
|
||||||
int sendBytes;
|
int sendBytes;
|
||||||
|
|
||||||
struct sockaddr_in serverAddress;
|
struct sockaddr_in serverAddress; // ip address of the server
|
||||||
struct sockaddr_in clientAddress;
|
struct sockaddr_in clientAddress; // ip address of the client
|
||||||
|
|
||||||
socketFd = socket(AF_INET, SOCK_STREAM, 0);
|
serverSocket = socket(AF_INET, SOCK_STREAM, 0); // create the server's endpoint
|
||||||
if(socketFd < 0) {
|
// AF_INET: address-family: internet (alias for IPV4, AF_INET6 for ipv6)
|
||||||
|
// SOCK_STREAM: two-way handshaked communication
|
||||||
|
// 0: use the default protocol for the given domain/type (SOCK_STREAM=TCP and SOCK_DGRAM=UDP)
|
||||||
|
if(serverSocket < 0) { // error-check the socket creation
|
||||||
logger_->log("TcpServer", LogFlag::Error, "Unable to open Server socket.");
|
logger_->log("TcpServer", LogFlag::Error, "Unable to open Server socket.");
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configure the socket
|
||||||
int on = 1;
|
int on = 1;
|
||||||
setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
|
// SOL_SOCKET: generic socket options family
|
||||||
|
// SO_REUSEADDR: allows the socket to bind to an idle port
|
||||||
|
// on: value to set the option to
|
||||||
|
|
||||||
serverAddress.sin_family = AF_INET;
|
// describe the IP address of the server
|
||||||
serverAddress.sin_port = htons(configuration_.port);
|
memset(&serverAddress.sin_zero, 0, sizeof(serverAddress.sin_zero)); // sin_zero is padding that must be clear
|
||||||
serverAddress.sin_addr.s_addr = INADDR_ANY;
|
serverAddress.sin_family = AF_INET; // socket-internet_family = ADDRESS_FAMILTY: INTERNET
|
||||||
memset(&serverAddress.sin_zero, 0, sizeof(serverAddress.sin_zero));
|
serverAddress.sin_port = htons(configuration_.port); // socket-internet_port = our port (endianess checked)
|
||||||
|
serverAddress.sin_addr.s_addr = INADDR_ANY; // socket-address = 0.0.0.0
|
||||||
|
|
||||||
if(bind(socketFd, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) {
|
// bind the server socket to the server's address
|
||||||
|
if(bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) {
|
||||||
logger_->log("TcpServer", LogFlag::Error, "Unable to bind server socket.");
|
logger_->log("TcpServer", LogFlag::Error, "Unable to bind server socket.");
|
||||||
return ErrorCode::Error;
|
return ErrorCode::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(buffer, 0x0, sizeof(buffer));
|
// configure for listening
|
||||||
listen(socketFd, 10);
|
memset(buffer, 0x0, sizeof(buffer)); // clear our buffer so we know for sure any data in it is the client's
|
||||||
|
listen(serverSocket, 10); // configure the socket as a passive server with a fifo queue 10 requests long
|
||||||
logger_->log("TcpServer", LogFlag::Debug, "Server listening on port {}...", configuration_.port);
|
logger_->log("TcpServer", LogFlag::Debug, "Server listening on port {}...", configuration_.port);
|
||||||
|
|
||||||
unsigned int sinSize = sizeof(struct sockaddr);
|
while(true) {
|
||||||
clientFd = accept(socketFd, (struct sockaddr*)&clientAddress, &sinSize);
|
|
||||||
if(clientFd < 0) {
|
// connnect to client when requested. successful connection creates the client socket
|
||||||
logger_->log("TcpServer", LogFlag::Error, "Unable to accept client socket.");
|
unsigned int clientAddressSize = sizeof(struct sockaddr);
|
||||||
return ErrorCode::Error;
|
clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressSize);
|
||||||
|
// accept() blocks until connected
|
||||||
|
// the sockaddr_in must be cast to the generic sockaddr struct
|
||||||
|
// accept() also writes the size of the incoming clientAddress
|
||||||
|
if(clientSocket < 0) { // error check that guy
|
||||||
|
logger_->log("TcpServer", LogFlag::Error, "Unable to accept client socket.");
|
||||||
|
// TODO: more robust errorchecking with errnos
|
||||||
|
return ErrorCode::Error;
|
||||||
|
}
|
||||||
|
logger_->log("TcpServer", LogFlag::Info
|
||||||
|
, "Client connected from {}:{}",
|
||||||
|
inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
|
||||||
|
|
||||||
|
// receive loop
|
||||||
|
while(1) {
|
||||||
|
// receive messages from the client. blocks until there's a message to receive
|
||||||
|
receiveBytes = recv(clientSocket, buffer, sizeof(buffer), 0);
|
||||||
|
// last arg is flags, 0=default
|
||||||
|
// MSG_PEEK: read without consuming the message from the queue
|
||||||
|
// MSG_WAITALL: block until all of the specified size is received
|
||||||
|
// MSG_DONTWAIT: non-blocking receive, returns -1 immediately if queue is empty
|
||||||
|
if(receiveBytes <= 0) break; // exit when there's nothing left to receive
|
||||||
|
|
||||||
|
logger_->log("TcpClient", LogFlag::Debug, "Received {} bytes from client: 0x{:x}", receiveBytes, buffer[0]);
|
||||||
|
|
||||||
|
// echo back received data back to the client
|
||||||
|
sendBytes = send(clientSocket, buffer, receiveBytes, 0); // TODO: send size is not guarenteed
|
||||||
|
if(sendBytes < 0) {
|
||||||
|
logger_->log("TcpServer", LogFlag::Error, "Unable to send to client.");
|
||||||
|
return ErrorCode::Error;
|
||||||
|
}
|
||||||
|
logger_->log("TcpClient", LogFlag::Debug, "Echoed {} bytes back to the client.", sendBytes);
|
||||||
|
|
||||||
|
} // TODO: configure a sigevent to catch a process exit signal into manually exiting this while loop
|
||||||
|
// so resources can be properly cleaned up by destructors
|
||||||
|
|
||||||
|
// error check receive
|
||||||
|
if(receiveBytes == 0) {
|
||||||
|
logger_->log("TcpClient", LogFlag::Info, "Client disconnected.");
|
||||||
|
} else if(receiveBytes < 0) {
|
||||||
|
logger_->log("TcpClient", LogFlag::Error, "Read from client failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
close(clientSocket);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_in peerAddress;
|
close(serverSocket);
|
||||||
unsigned int len = sizeof(peerAddress);
|
|
||||||
char serverIp[20];
|
|
||||||
logger_->log("TcpServer", LogFlag::Debug, "Accept socket... Client address: {} Port: {}", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
|
|
||||||
getsockname(clientFd, (struct sockaddr*)&peerAddress, &len);
|
|
||||||
inet_ntop(AF_INET, &peerAddress, serverIp, sizeof(serverIp));
|
|
||||||
logger_->log("TcpServer", LogFlag::Debug, "Accept socket... Server address: {}", serverIp);
|
|
||||||
|
|
||||||
receiveBytes = recv(clientFd, buffer, sizeof(buffer), 0);
|
|
||||||
if(receiveBytes < 0) {
|
|
||||||
logger_->log("TcpServer", LogFlag::Error, "Unable to receive from client.");
|
|
||||||
return ErrorCode::Error;
|
|
||||||
}
|
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Received {} bytes from client: 0x{:x}", receiveBytes, buffer[2]);
|
|
||||||
|
|
||||||
// echo back
|
|
||||||
sendBytes = send(clientFd, buffer, sizeof(buffer), 0);
|
|
||||||
if(sendBytes < 0) {
|
|
||||||
logger_->log("TcpServer", LogFlag::Error, "Unable to send to client.");
|
|
||||||
return ErrorCode::Error;
|
|
||||||
}
|
|
||||||
logger_->log("TcpClient", LogFlag::Debug, "Echoed {} bytes back to the client.", sendBytes);
|
|
||||||
|
|
||||||
close(socketFd);
|
|
||||||
|
|
||||||
return ErrorCode::Success;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user