Working Server and Client
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
*.o
|
*.o
|
||||||
netpong
|
netpong
|
||||||
netpong.dSYM/
|
netpong.dSYM/
|
||||||
|
netpong.c
|
||||||
|
|||||||
4
court.c
4
court.c
@@ -6,7 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void DrawWalls(struct GameData data)
|
void DrawWalls(GameData data)
|
||||||
{
|
{
|
||||||
for (int i = LEFT_COL; i <= RIGHT_COL; i++) {
|
for (int i = LEFT_COL; i <= RIGHT_COL; i++) {
|
||||||
move(TOP_ROW, i);
|
move(TOP_ROW, i);
|
||||||
@@ -25,7 +25,7 @@ void DrawWalls(struct GameData data)
|
|||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
void DrawHeader(struct GameData data)
|
void DrawHeader(GameData data)
|
||||||
{
|
{
|
||||||
move(TOP_ROW - 2, LEFT_COL);
|
move(TOP_ROW - 2, LEFT_COL);
|
||||||
addch('P');
|
addch('P');
|
||||||
|
|||||||
9
game.h
9
game.h
@@ -7,16 +7,17 @@
|
|||||||
#define LEFT_COL 9
|
#define LEFT_COL 9
|
||||||
#define RIGHT_COL 70
|
#define RIGHT_COL 70
|
||||||
|
|
||||||
struct GameData
|
typedef struct
|
||||||
{
|
{
|
||||||
|
int host;
|
||||||
int playerNumber;
|
int playerNumber;
|
||||||
char* domain;
|
char* domain;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
};
|
} GameData;
|
||||||
|
|
||||||
|
|
||||||
void DrawWalls(struct GameData);
|
void DrawWalls(GameData);
|
||||||
void DrawHeader(struct GameData);
|
void DrawHeader(GameData);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
139
main.c
139
main.c
@@ -3,20 +3,24 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "network/networking.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Fucntion
|
* Main Fucntion
|
||||||
*/
|
*/
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
// Create GameData Object
|
// Create GameData Object
|
||||||
struct GameData data;
|
GameData data = { false, 0, NULL, 0 };
|
||||||
|
|
||||||
// Detect Server or Client
|
// Detect Server or Client
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 2:
|
case 2:
|
||||||
// Start Server
|
// Start Server
|
||||||
|
data.host = true;
|
||||||
data.playerNumber = 0;
|
data.playerNumber = 0;
|
||||||
data.port = atoi(argv[1]);
|
data.port = atoi(argv[1]);
|
||||||
break;
|
break;
|
||||||
@@ -34,27 +38,130 @@ int main(int argc, char* argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(getpid());
|
// srand(getpid());
|
||||||
|
|
||||||
// Setup Terminal
|
// // Setup Terminal
|
||||||
if (initscr() == NULL) {
|
// if (initscr() == NULL) {
|
||||||
perror("initscr failed");
|
// perror("initscr failed");
|
||||||
exit(1);
|
// exit(1);
|
||||||
|
// }
|
||||||
|
// noecho();
|
||||||
|
// cbreak();
|
||||||
|
// nodelay(stdscr, TRUE);
|
||||||
|
|
||||||
|
int game_running = true;
|
||||||
|
|
||||||
|
if (data.host) {
|
||||||
|
// Create Server
|
||||||
|
Server s = StartServer(data.port);
|
||||||
|
|
||||||
|
printf("Server Started\n");
|
||||||
|
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(s.server_fd, &fds);
|
||||||
|
|
||||||
|
struct timeval tv = { 0, 0 }; // non-blocking check
|
||||||
|
|
||||||
|
int updateChar = 0;
|
||||||
|
|
||||||
|
while (game_running) {
|
||||||
|
fd_set read_fds;
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
|
||||||
|
// Add server socket
|
||||||
|
FD_SET(s.server_fd, &read_fds);
|
||||||
|
int max_fd = s.server_fd;
|
||||||
|
|
||||||
|
// Add client sockets
|
||||||
|
for (int i = 0; i < s.client_count; i++) {
|
||||||
|
int fd = s.clients[i];
|
||||||
|
FD_SET(fd, &read_fds);
|
||||||
|
if (fd > max_fd)
|
||||||
|
max_fd = fd;
|
||||||
}
|
}
|
||||||
noecho();
|
|
||||||
cbreak();
|
|
||||||
nodelay(stdscr, TRUE);
|
|
||||||
|
|
||||||
DrawWalls(data);
|
// Small timeout (prevents 100% CPU usage)
|
||||||
DrawHeader(data);
|
struct timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 1000; // 1ms
|
||||||
|
|
||||||
int socket_fd = 0;
|
int ret = select(max_fd + 1, &read_fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
while (1) {
|
if (ret < 0) {
|
||||||
int ch = getch();
|
perror("select");
|
||||||
if (ch == 'q')
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
endwin();
|
// New connection
|
||||||
|
if (FD_ISSET(s.server_fd, &read_fds)) {
|
||||||
|
int client_fd = accept(s.server_fd, NULL, NULL);
|
||||||
|
if (client_fd >= 0 && s.client_count < s.max_clients) {
|
||||||
|
s.clients[s.client_count++] = client_fd;
|
||||||
|
printf("New client connected: %d\n", client_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle client data
|
||||||
|
for (int i = 0; i < s.client_count; i++) {
|
||||||
|
int fd = s.clients[i];
|
||||||
|
|
||||||
|
if (FD_ISSET(fd, &read_fds)) {
|
||||||
|
char buffer[1024];
|
||||||
|
int bytes = recv(fd, buffer, sizeof(buffer) - 1, 0);
|
||||||
|
|
||||||
|
if (bytes > 0) {
|
||||||
|
buffer[bytes] = '\0';
|
||||||
|
printf("Client %d says: %s\n", fd, buffer);
|
||||||
|
|
||||||
|
// Example: echo back
|
||||||
|
send(fd, buffer, bytes, 0);
|
||||||
|
} else if (bytes == 0) {
|
||||||
|
printf("Client %d disconnected\n", fd);
|
||||||
|
RemoveClient(&s, i);
|
||||||
|
i--; // re-check swapped client
|
||||||
|
} else {
|
||||||
|
perror("recv");
|
||||||
|
RemoveClient(&s, i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s.server_fd);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
printf("Connecting to %s:%i\n", data.domain, data.port);
|
||||||
|
|
||||||
|
// Create Client
|
||||||
|
|
||||||
|
Client c = StartClient(data.domain, data.port);
|
||||||
|
|
||||||
|
char* msg = "Hello from client";
|
||||||
|
send(c.client_fd, msg, strlen(msg), 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[1024] = { 0 };
|
||||||
|
read(c.client_fd, buffer, sizeof(buffer));
|
||||||
|
printf("Server: %s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(10);
|
||||||
|
char* msg2 = "Ok I am leaving now";
|
||||||
|
send(c.client_fd, msg2, strlen(msg2), 0);
|
||||||
|
{
|
||||||
|
char buffer[1024] = { 0 };
|
||||||
|
read(c.client_fd, buffer, sizeof(buffer));
|
||||||
|
printf("Server: %s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(c.client_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// endwin();
|
||||||
}
|
}
|
||||||
88
network/networking.c
Normal file
88
network/networking.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include "networking.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
Server StartServer(int port) {
|
||||||
|
Server s = {2};
|
||||||
|
s.clientID = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Create Socket
|
||||||
|
if ((s.server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
||||||
|
perror("socket failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Address
|
||||||
|
s.address.sin_family = AF_INET;
|
||||||
|
s.address.sin_addr.s_addr = INADDR_ANY; // listen on all interfaces
|
||||||
|
s.address.sin_port = htons(port);
|
||||||
|
|
||||||
|
// Bind Port
|
||||||
|
if (bind(s.server_fd, (struct sockaddr *)&s.address, sizeof(s.address)) < 0) {
|
||||||
|
perror("bind failed");
|
||||||
|
close(s.server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for incoming connections
|
||||||
|
if (listen(s.server_fd, 3) < 0) {
|
||||||
|
perror("listen");
|
||||||
|
close(s.server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Server listening on port %d...\n", port);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveClient(Server* s, int index) {
|
||||||
|
close(s->clients[index]);
|
||||||
|
s->clients[index] = s->clients[s->client_count - 1];
|
||||||
|
s->client_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client StartClient(char* host, int port) {
|
||||||
|
|
||||||
|
Client c;
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
if ((c.client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
perror("socket failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set address info
|
||||||
|
c.address.sin_family = AF_INET;
|
||||||
|
c.address.sin_port = htons(port);
|
||||||
|
|
||||||
|
// Convert hostname/IP to binary form
|
||||||
|
if (inet_pton(AF_INET, host, &c.address.sin_addr) <= 0) {
|
||||||
|
// If not a direct IP, try resolving hostname
|
||||||
|
struct hostent* he = gethostbyname(host);
|
||||||
|
if (he == NULL) {
|
||||||
|
perror("gethostbyname failed");
|
||||||
|
close(c.client_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
memcpy(&c.address.sin_addr, he->h_addr_list[0], he->h_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to server
|
||||||
|
if (connect(c.client_fd, (struct sockaddr*)&c.address, sizeof(c.address)) < 0) {
|
||||||
|
perror("connect failed");
|
||||||
|
close(c.client_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connected to %s:%d\n", host, port);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
26
network/networking.h
Normal file
26
network/networking.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef GAME_NETWORKING_H
|
||||||
|
#define GAME_NETWORKING_H 1
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const int max_clients;
|
||||||
|
int server_fd;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
int clients[2];
|
||||||
|
int clientID;
|
||||||
|
int client_count;
|
||||||
|
} Server;
|
||||||
|
|
||||||
|
Server StartServer(int port);
|
||||||
|
void RemoveClient(Server* s, int index);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int client_fd;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
} Client;
|
||||||
|
|
||||||
|
|
||||||
|
Client StartClient(char* host, int port);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user