04_intro_to_sockets: working tcp example

add .gitignore and remove executeables and object files
This commit is contained in:
Daniel Meiburg 2024-05-16 01:13:49 +02:00
parent a29cccd3ea
commit 66c8612401
Signed by: dm
GPG Key ID: E5827ECFFE0AA4F2
9 changed files with 188 additions and 18 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
obj/
bin/

View File

@ -13,6 +13,7 @@ static struct gpiod_line *button_line = NULL;
// Error handling function // Error handling function
static int handle_error(const char *msg) { static int handle_error(const char *msg) {
perror(msg); perror(msg);
cleanup_gpio()
return -1; return -1;
} }

View File

@ -1,10 +1,11 @@
# Compiler and flags
CC = gcc CC = gcc
CFLAGS = -Wall -Ilib CFLAGS = -Wall -Ilib
#LDFLAGS = -lgpiod
# Directories # Directories
SRCDIR = src SRCDIR = src
LIBDIR = lib LIBDIR = lib
BINDIR = bin
OBJDIR = obj OBJDIR = obj
# Source files # Source files
@ -13,27 +14,26 @@ SRC_SOURCES = $(wildcard $(SRCDIR)/*.c)
# Object files # Object files
LIB_OBJECTS = $(LIB_SOURCES:$(LIBDIR)/%.c=$(OBJDIR)/%.o) LIB_OBJECTS = $(LIB_SOURCES:$(LIBDIR)/%.c=$(OBJDIR)/%.o)
SRC_OBJECTS = $(SRC_SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
# Target executable # Executables
TARGET = sockets EXECS = $(SRC_SOURCES:$(SRCDIR)/%.c=$(BINDIR)/%)
# Create obj directory if it doesn't exist # Create necessary directories
$(shell mkdir -p $(OBJDIR)) $(shell mkdir -p $(OBJDIR))
$(shell mkdir -p $(BINDIR))
# Rules # Rules
all: $(TARGET) all: $(EXECS)
$(TARGET): $(LIB_OBJECTS) $(SRC_OBJECTS) $(BINDIR)/%: $(SRCDIR)/%.c $(LIB_OBJECTS)
$(CC) $(LIB_OBJECTS) $(SRC_OBJECTS) -o $@ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $< $(LIB_OBJECTS)
$(OBJDIR)/%.o: $(LIBDIR)/%.c $(OBJDIR)/%.o: $(LIBDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
clean: clean:
rm -f $(OBJDIR)/*.o $(TARGET) rm -f $(OBJDIR)/*.o
rm -f $(BINDIR)/*
.PHONY: all clean .PHONY: all clean

View File

@ -7,5 +7,5 @@ a LED, a button and a temperature sensor.
```bash ```bash
$ make $ make
$ ./io $ ./sockets
``` ```

View File

@ -0,0 +1,113 @@
#include <arpa/inet.h> // For inet_addr(), htons()
#include <stdio.h> // For printf()
#include <stdlib.h> // For exit()
#include <string.h> // For memset()
#include <sys/socket.h> // For socket(), connect(), read(), write()
#include <time.h>
#include <unistd.h> // For close()
#include "sockets.h"
#define BUFFER_SIZE 1024
static void error_handling(char *message, int sock) {
perror(message);
close(sock);
exit(1);
}
int tcp_create_socket() {
// PF_INET: IPv4, SOCK_STREAM: TCP
int sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1)
error_handling("socket() error", sock);
return sock;
}
void connect_to_server(int sock, char *ip, int port) {
struct sockaddr_in serv_addr;
// Initialize serv_addr to zero
memset(&serv_addr, 0, sizeof(serv_addr));
// Set the address family to IPv4
serv_addr.sin_family = AF_INET;
// Convert IP address to binary form
serv_addr.sin_addr.s_addr = inet_addr(ip);
// Convert port number to network byte order
serv_addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error", sock);
}
char* communicate(int sock, char *message) {
// Sending the ASCII string
if (write(sock, message, strlen(message)) == -1)
error_handling("write() error", sock);
// Receiving response
char* response = malloc(BUFFER_SIZE);
if (!response)
error_handling("Failed to allocate memory for response", sock);
int str_len = read(sock, response, BUFFER_SIZE - 1);
if (str_len == -1){
free(response);
error_handling("read() error", sock);
} else if (str_len == 0) {
printf("Server closed the connection.\n");
free(response);
return NULL;
} else {
response[str_len] = '\0'; // Null-terminate the received data
}
return response;
}
int tcp_listen(int port) {
int sock = tcp_create_socket();
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("bind() error", sock);
if (listen(sock, 5) == -1)
error_handling("listen() error", sock);
return sock;
}
int tcp_accept(int serv_sock) {
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if (clnt_sock == -1)
error_handling("accept() error", clnt_sock);
return clnt_sock;
}
void process_request(int clnt_sock) {
char message[BUFFER_SIZE];
int str_len = read(clnt_sock, message, BUFFER_SIZE - 1);
if (str_len == -1)
// TODO: clnt_sock might be a bug
error_handling("read() error", clnt_sock);
message[str_len] = '\0'; // Null-terminate the string
time_t t = time(NULL);
struct tm *timeinfo;
if (strcmp(message, "1") == 0) {
timeinfo = localtime(&t); // Local time
} else {
timeinfo = gmtime(&t); // GMT time
}
strftime(message, BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", timeinfo);
write(clnt_sock, message, strlen(message));
}

View File

@ -1,5 +1,22 @@
#ifndef SOCKETS_LIB_H #ifndef SOCKETS_LIB_H
#define SOCKETS_LIB_H #define SOCKETS_LIB_H
// Function to create a TCP socket
int tcp_create_socket();
#endif // SOCKETS_H // Function to connect to a server
void connect_to_server(int sock, char *ip, int port);
// Function to communicate with the server
char* communicate(int sock, char *message);
// Function to create a TCP server socket
int tcp_listen(int port);
// Function to accept a client connection
int tcp_accept(int serv_sock);
// Function to process a client request
void process_request(int clnt_sock);
#endif // SOCKETS_LIB_H

View File

@ -0,0 +1,21 @@
#include <stdio.h> // For printf()
#include <unistd.h> // For close()
#include <stdlib.h> // For exit(), atoi()
#include "sockets.h"
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("Usage : %s <IP> <port> <message_to_send>\n", argv[0]);
exit(1);
}
int sock = tcp_create_socket();
connect_to_server(sock, argv[1], atoi(argv[2]));
char* received_data = communicate(sock, argv[3]);
if (received_data) {
printf("Received from server: %s\n", received_data);
free(received_data);
}
close(sock);
return 0;
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "sockets.h"
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <port>\n", argv[0]);
exit(1);
}
int port = atoi(argv[1]);
int serv_sock = tcp_listen(port);
int clnt_sock = tcp_accept(serv_sock);
process_request(clnt_sock);
close(clnt_sock);
close(serv_sock);
return 0;
}

View File

@ -1,4 +0,0 @@
int main() {
return 0;
}