Initial basic messaging server.
This commit is contained in:
commit
efd17b030e
4 changed files with 216 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
.cache
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
cmake_install.cmake
|
||||||
|
compile_commands.json
|
||||||
|
.dir-locals.el
|
||||||
|
Makefile
|
||||||
|
Urchin-*
|
||||||
28
CMakeLists.txt
Normal file
28
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(Urchin
|
||||||
|
VERSION 0
|
||||||
|
DESCRIPTION "Simple Mud Experiment in C"
|
||||||
|
HOMEPAGE_URL "https://git.warwick-new.co.uk/"
|
||||||
|
LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 90)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
set(CMAKE_C_CLANG_TIDY)
|
||||||
|
|
||||||
|
# Compile Server
|
||||||
|
file(GLOB_RECURSE SERVER_SOURCE_FILES
|
||||||
|
${CMAKE_SOURCE_DIR}/src/server/*.c)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SERVER_HEADER_FILES
|
||||||
|
${CMAKE_SOURCE_DIR}/src/server/*.h)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}-server ${SERVER_HEADER_FILES} ${SERVER_SOURCE_FILES})
|
||||||
|
|
||||||
|
# Compile Client
|
||||||
|
file(GLOB_RECURSE CLIENT_SOURCE_FILES
|
||||||
|
${CMAKE_SOURCE_DIR}/src/client/*.c)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE CLIENT_HEADER_FILES
|
||||||
|
${CMAKE_SOURCE_DIR}/src/client/*.h)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}-client ${CLIENT_HEADER_FILES} ${CLIENT_SOURCE_FILES})
|
||||||
79
src/client/main.c
Normal file
79
src/client/main.c
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
// Sorry in advance for all the comments. This project is also a way for me to
|
||||||
|
// learn C.
|
||||||
|
|
||||||
|
#include <netdb.h> // Contains host structure
|
||||||
|
#include <netinet/in.h> //sockaddr_in
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> // Keeping for conversion functions
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/socket.h> // sockaddr
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
void error_crash(const char *msg) {
|
||||||
|
fprintf(stderr, "error crash: %s\n", msg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void error_warn(const char *msg) { fprintf(stderr, "warning: %s\n", msg); }
|
||||||
|
|
||||||
|
// TODO: Save the logs somewhere
|
||||||
|
void error_log(const char *msg) { fprintf(stderr, "log: %s\n", msg); }
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// Set up containers for file descriptor id's
|
||||||
|
int sockfd, portno, errflag;
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
|
bzero((char *)&serv_addr, sizeof(serv_addr));
|
||||||
|
struct hostent *server;
|
||||||
|
char msgbuffer[255];
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
error_crash("Not enough server info has been provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
portno = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
portno = 3940;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0)
|
||||||
|
error_crash("Can't open socket.");
|
||||||
|
|
||||||
|
server = gethostbyname(argv[1]);
|
||||||
|
if (server == NULL)
|
||||||
|
error_crash("No such host exists :(");
|
||||||
|
|
||||||
|
serv_addr.sin_family = AF_INET;
|
||||||
|
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
|
||||||
|
server->h_length);
|
||||||
|
serv_addr.sin_port = htons(portno);
|
||||||
|
errflag = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||||
|
if (errflag < 0)
|
||||||
|
error_crash("Failed to connect to host");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
bzero(msgbuffer, sizeof msgbuffer);
|
||||||
|
fgets(msgbuffer, sizeof msgbuffer, stdin);
|
||||||
|
errflag = write(sockfd, msgbuffer, strlen(msgbuffer));
|
||||||
|
if (errflag < 0)
|
||||||
|
error_crash("Failed to write message");
|
||||||
|
|
||||||
|
bzero(msgbuffer, sizeof msgbuffer);
|
||||||
|
errflag = read(sockfd, msgbuffer, sizeof msgbuffer);
|
||||||
|
if (errflag < 0)
|
||||||
|
error_crash("Failed to read message");
|
||||||
|
|
||||||
|
printf("Server: %s", msgbuffer);
|
||||||
|
|
||||||
|
int cmp = strncmp("Bye", msgbuffer, 3);
|
||||||
|
if (cmp == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sockfd);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
101
src/server/main.c
Normal file
101
src/server/main.c
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Sorry in advance for all the comments. This project is also a way for me to
|
||||||
|
// learn C.
|
||||||
|
|
||||||
|
#include <netinet/in.h> //sockaddr_in
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> // Keeping for conversion functions
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/socket.h> // sockaddr
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
void error_crash(const char *msg) {
|
||||||
|
fprintf(stderr, "error crash: %s\n", msg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void error_warn(const char *msg) { fprintf(stderr, "warning: %s\n", msg); }
|
||||||
|
|
||||||
|
// TODO: Save the logs somewhere
|
||||||
|
void error_log(const char *msg) { fprintf(stderr, "log: %s\n", msg); }
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// Set up containers for file descriptor id's
|
||||||
|
int sockfd, clientsockfd, portno, errflag;
|
||||||
|
char msgbuffer[255];
|
||||||
|
|
||||||
|
// Set port number.
|
||||||
|
if (argc > 1) {
|
||||||
|
portno = atoi(argv[1]);
|
||||||
|
} else {
|
||||||
|
portno = 3940;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Socket address info
|
||||||
|
struct sockaddr_in serv_addr, cli_addr;
|
||||||
|
socklen_t clilen = sizeof cli_addr; // We can do this here as cli_addr isn't
|
||||||
|
// touched until it's used
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0) {
|
||||||
|
error_crash("Can't open socket.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure there is no junk data in serve_addr
|
||||||
|
bzero((char *)&serv_addr, sizeof serv_addr);
|
||||||
|
|
||||||
|
// Tell the connection to use ipv4 and port number
|
||||||
|
serv_addr.sin_family = AF_INET;
|
||||||
|
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
serv_addr.sin_port = htons(portno);
|
||||||
|
|
||||||
|
// Bind Socket
|
||||||
|
errflag = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||||
|
if (errflag < 0) {
|
||||||
|
error_crash("Can't bind socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
errflag = listen(sockfd, 5);
|
||||||
|
if (errflag < 0) {
|
||||||
|
error_crash("Can't listen for connections");
|
||||||
|
}
|
||||||
|
|
||||||
|
char portstr[5]; // Buffer to store string version of port
|
||||||
|
snprintf(portstr, sizeof portstr, "%d", portno);
|
||||||
|
printf("Server Listening on port: %s\n", portstr);
|
||||||
|
|
||||||
|
clientsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
|
||||||
|
if (clientsockfd < 0) {
|
||||||
|
error_crash("Can't accept connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Empty message buffer
|
||||||
|
bzero(msgbuffer, sizeof msgbuffer);
|
||||||
|
|
||||||
|
errflag = read(clientsockfd, msgbuffer, sizeof msgbuffer);
|
||||||
|
if (errflag < 0) {
|
||||||
|
error_crash("Didn't recieve message from connection");
|
||||||
|
}
|
||||||
|
printf("Client: %s\n", msgbuffer);
|
||||||
|
|
||||||
|
// clear buffer for writing
|
||||||
|
bzero(msgbuffer, sizeof msgbuffer);
|
||||||
|
fgets(msgbuffer, sizeof msgbuffer, stdin);
|
||||||
|
|
||||||
|
errflag = write(clientsockfd, msgbuffer, strlen(msgbuffer));
|
||||||
|
if (errflag < 0) {
|
||||||
|
error_crash("Couldn't write response message");
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = strncmp("Bye", msgbuffer, 3);
|
||||||
|
if (cmp == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(clientsockfd);
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue