This commit is contained in:
2025-11-11 23:01:19 +00:00
parent 1a27d39974
commit 6805e85f43
11 changed files with 387 additions and 7 deletions
+22
View File
@@ -0,0 +1,22 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
{
"name": "Ubuntu",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/base:noble"
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
BIN
View File
Binary file not shown.
+112
View File
@@ -0,0 +1,112 @@
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define SERVER_IP_ADDRESS "127.0.0.1"
#define SERVER_PORT 10059
#define HEADER_SIZE 4
#define CHUNK_SIZE 1024
#define TOTAL_CHUNKS 1024
int main(int argc, char *argv[])
{
int socket_desc;
struct sockaddr_in server;
// Create socket
socket_desc = socket(AF_INET, SOCK_DGRAM, 0);
// Server address structure
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IP_ADDRESS, &(server.sin_addr));
// Send initial message to the server
// We want the entire file initially
sendto(socket_desc, "INI", 3, 0, (struct sockaddr *)&server, sizeof(server));
// Ack Buffer
char ack_buffer[TOTAL_CHUNKS];
for (int i = 0; i < TOTAL_CHUNKS; i++) {
ack_buffer[i] = 0; // Initialize all to not received
}
// Buffer for entire file
char file_buffer[CHUNK_SIZE * TOTAL_CHUNKS];
FILE *file = fopen("received_ugbits.txt", "w");
listen_for_file:
printf("Listening for file chunks...\n");
// Set socket timeout to 5 seconds
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
setsockopt(socket_desc, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
// Listen for file messages from the server
while (1)
{
char buffer[CHUNK_SIZE + HEADER_SIZE];
socklen_t server_len = sizeof(server);
int recv_size = recvfrom(socket_desc, buffer, CHUNK_SIZE + HEADER_SIZE, 0, (struct sockaddr *)&server, &server_len);
if (recv_size < 0) {
// Timeout occurred - no message received for 5 seconds
printf("No messages received for 5 seconds, stopping...\n");
break;
} else {
buffer[recv_size] = '\0';
char chunkNum[5];
strncpy(chunkNum, buffer, HEADER_SIZE);
chunkNum[HEADER_SIZE] = '\0';
// printf("Received Chunk: %s\n", chunkNum);
ack_buffer[atoi(chunkNum)] = 1; // Set buffer to RXed
// Method 1: Store chunk in buffer var
memcpy(file_buffer + (atoi(chunkNum) - 1) * CHUNK_SIZE, buffer + HEADER_SIZE, recv_size - HEADER_SIZE);
// Method 2: Write chunk directly to file
// fseek(file, (atoi(chunkNum) - 1) * CHUNK_SIZE, SEEK_SET);
// fwrite(buffer + HEADER_SIZE, 1, recv_size - HEADER_SIZE, file);
}
}
// If any chunk has not been received, request missing chunks
// This is accomplished by sending the ack buffer back to the server
int totalMissing = 0;
for (int i = 1; i <= TOTAL_CHUNKS; i++) {
if (ack_buffer[i] != 1) {
totalMissing++;
}
}
if (totalMissing != 0) {
printf("Total missing chunks: %d, requesting retransmission...\n", totalMissing);
char request[TOTAL_CHUNKS + HEADER_SIZE];
snprintf(request, sizeof(request), "REQ");
memcpy(request + HEADER_SIZE, ack_buffer, TOTAL_CHUNKS);
sendto(socket_desc, request, strlen(request), 0, (struct sockaddr *)&server, sizeof(server));
goto listen_for_file;
}
// If we made it here, the file must be complete.
printf("File transfer complete!\n");
// Method 1: Write entire buffer to file
fwrite(file_buffer, 1, CHUNK_SIZE * TOTAL_CHUNKS, file);
fclose(file);
close(socket_desc);
return 0;
}
+7 -7
View File
@@ -1,7 +1,7 @@
## cos440-hw4 ##
[![](https://gitea-actions.nicholaspease.com/actions/umaine-npease/cos440-hw4/badge?label=build&style=flat&branch=main)](https://gitea-actions.nicholaspease.com/latest-log?branch=main)
[![](https://drone.nicholaspease.com/api/badges/umaine-npease/cos440-hw4/status.svg)](https://drone.nicholaspease.com/umaine-npease/cos440-hw4)
[![](https://wakaapi.nicholaspease.com/api/badge/LAX18/interval:any/project:cos440-hw4)](https://wakaapi.nicholaspease.com/summary?interval=any&project=cos440-hw4)
![](https://server1.nicholaspease.com/badges/cloc/npease/cos440-hw4.svg)
<hr>
## cos440-hw4 ##
[![](https://gitea-actions.nicholaspease.com/actions/umaine-npease/cos440-hw4/badge?label=build&style=flat&branch=main)](https://gitea-actions.nicholaspease.com/latest-log?branch=main)
[![](https://drone.nicholaspease.com/api/badges/umaine-npease/cos440-hw4/status.svg)](https://drone.nicholaspease.com/umaine-npease/cos440-hw4)
[![](https://wakaapi.nicholaspease.com/api/badge/LAX18/interval:any/project:cos440-hw4)](https://wakaapi.nicholaspease.com/summary?interval=any&project=cos440-hw4)
![](https://server1.nicholaspease.com/badges/cloc/npease/cos440-hw4.svg)
<hr>
+96
View File
@@ -0,0 +1,96 @@
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#define SERVER_IP_ADDRESS "127.0.0.1"
#define SERVER_PORT 10059
#define HEADER_SIZE 4
#define CHUNK_SIZE 1024
#define TOTAL_CHUNKS 1024
#define AWK_BUFFER_SIZE 1024
int send_size, recv_size;
int main(int argc, char *argv[])
{
int socket_desc, c, read_size; // socket and such
struct sockaddr_in server, client; // one for server one for client address info
char client_message[HEADER_SIZE + AWK_BUFFER_SIZE]; // Buffer (entire AWK buffer + requested chunk)
socket_desc = socket(AF_INET, SOCK_DGRAM, 0);
printf("SETUP: Socket Created\n");
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IP_ADDRESS, &(server.sin_addr));
bind(socket_desc, (struct sockaddr *)&server, sizeof(server));
printf("SETUP: Bind Completed \n\n");
c = sizeof(struct sockaddr_in);
// Start waiting for any messages inbound
FILE *file = fopen("ugbits.txt", "r");
while (1)
{
recv_size = recvfrom(socket_desc, client_message, HEADER_SIZE + AWK_BUFFER_SIZE, 0, (struct sockaddr *)&client, (socklen_t *)&c);
if (recv_size < 0)
{
perror("Receive Failed");
continue;
}
client_message[recv_size] = '\0';
char response[1025];
if (strncmp(client_message, "INI", 3) == 0) {
printf("Initial Send Request Received\n");
char buffer[CHUNK_SIZE];
int chunk_number = 1;
size_t bytes_read;
fseek(file, 0, SEEK_SET); // Reset file pointer to beginning
for (int i = 0; i < TOTAL_CHUNKS; i++) {
bytes_read = fread(buffer, 1, CHUNK_SIZE, file);
char chunk_response[HEADER_SIZE + CHUNK_SIZE];
snprintf(chunk_response, HEADER_SIZE + 1, "%04d", chunk_number);
memcpy(chunk_response + HEADER_SIZE, buffer, bytes_read);
send_size = sendto(socket_desc, chunk_response, HEADER_SIZE + bytes_read, 0, (struct sockaddr *)&client, c);
// printf("Sent chunk %d (%ld bytes)\n", chunk_number, bytes_read);
chunk_number++;
}
} else if (strncmp(client_message,"REQ", 3) == 0) {
char ack_buffer[AWK_BUFFER_SIZE];
memcpy(ack_buffer, client_message + HEADER_SIZE, AWK_BUFFER_SIZE);
printf("Retransmit Request Received\n");
for (int i = 1; i <= TOTAL_CHUNKS; i++) {
if (ack_buffer[i] != 1) {
fseek(file, (i - 1) * CHUNK_SIZE, SEEK_SET);
char buffer[CHUNK_SIZE];
size_t bytes_read = fread(buffer, 1, CHUNK_SIZE, file);
char chunk_response[HEADER_SIZE + CHUNK_SIZE];
snprintf(chunk_response, HEADER_SIZE + 1, "%04d", i);
memcpy(chunk_response + HEADER_SIZE, buffer, bytes_read);
send_size = sendto(socket_desc, chunk_response, HEADER_SIZE + bytes_read, 0, (struct sockaddr *)&client, c);
}
}
}
}
fclose(file);
close(socket_desc);
return 0;
}
BIN
View File
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
+54
View File
@@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <netdb.h>
struct sockaddr_in sa;
int main()
{
int chunkSize;
int fileSize;
int my_sock = socket(AF_INET, SOCK_STREAM, 0);
sa.sin_family = AF_INET;
sa.sin_port = htons(10059);
inet_pton(AF_INET, "127.0.0.1", &(sa.sin_addr));
int x = connect(my_sock, (struct sockaddr *)&sa, sizeof(sa));
// Request File Size
printf("\nRequesting File Size\n");
send(my_sock, "FS", 2, 0);
char size_buff[13];
int recv_size = recv(my_sock, size_buff, 13, 0);
fileSize = atoi(strtok(size_buff, "|"));
chunkSize = atoi(strtok(NULL, "|"));
// Server Transfer Settings
printf("File Size: %d\n", fileSize);
printf("Chunk Size: %d\n", chunkSize);
// Request File
printf("\nRequesting File Transfer\n");
send(my_sock, "RX", 2, 0);
int total_bytes_received = 0;
FILE *fp = fopen("rx.txt", "w");
char file_buffer[chunkSize];
while(total_bytes_received < fileSize) {
int bytes_received = recv(my_sock, file_buffer, chunkSize, 0);
if (bytes_received <= 0) {break;}
total_bytes_received += bytes_received;
fwrite(file_buffer, 1, bytes_received, fp);
printf("Received %d bytes, Total: %d bytes\n", bytes_received, total_bytes_received);
}
// Calculate MD5 checksum using system command
printf("\nCalculating MD5 checksum...\n");
printf("Expected Checksum:\n");
system("md5sum bits.txt | awk '{ print $1 }'");
printf("Received File Checksum: \n");
system("md5sum rx.txt | awk '{ print $1 }'");
fclose(fp);
}
+94
View File
@@ -0,0 +1,94 @@
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#define CHUNK_SIZE 2048
int send_size, recv_size;
int main(int argc, char *argv[])
{
int socket_desc, client_sock, c, read_size; // sockets and such
struct sockaddr_in server, client; // one for listening one for connection with client(s)
char client_message[20000];
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
client_sock = socket(AF_INET, SOCK_STREAM, 0);
printf("Sockets created\n");
server.sin_family = AF_INET;
server.sin_port = htons(10059);
inet_pton(AF_INET, "127.0.0.1", &(server.sin_addr));
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("bind failed. Error"); // perror is a very helpful function for tracking down errors
return 1;
}
printf("bind completed \n");
c = sizeof(struct sockaddr_in);
listen(socket_desc, 1);
printf("Waiting for incoming connections...\n");
// Start waiting for any connections inbound
while (1)
{
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c);
if (client_sock < 0)
{
perror("Accept Failed");
}
printf("\nClient Connected\n");
while (1)
{
recv_size = recv(client_sock, client_message, 2, 0);
long fileSize;
if (recv_size == 0)
{
printf("Client disconnected\n");
break;
}
client_message[recv_size] = '\0';
printf("Received %d bytes. Msg is %s \n", recv_size, client_message);
// Determine type of message
if (strncmp(client_message, "FS", 2) == 0)
{
// Send size of the file
FILE *fp = fopen("bits.txt", "rb");
fseek(fp, 0, SEEK_END);
fileSize = ftell(fp);
fclose(fp);
sprintf(client_message, "%ld|%d", fileSize, CHUNK_SIZE);
send_size = send(client_sock, client_message, strlen(client_message), 0);
if (send_size < 0)
perror("send failed");
}
else if (strncmp(client_message, "RX", 2) == 0)
{
// Client ready to receive file
FILE *fp = fopen("bits.txt", "rb");
char buffer[CHUNK_SIZE];
for(int i = 0; i < fileSize; i += CHUNK_SIZE) {
size_t bytesRead = fread(buffer, 1, CHUNK_SIZE, fp);
if (bytesRead > 0) {
send_size = send(client_sock, buffer, bytesRead, 0);
}
}
}
else
{
printf("Unknown message type\n");
}
}
}
close(socket_desc);
close(client_sock);
return 0;
}
+1
View File
File diff suppressed because one or more lines are too long