-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
153 lines (127 loc) · 4.3 KB
/
server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>
#define SA struct sockaddr
#define CHUNK_SIZE 1024 // Size of the chunks we'll split the file up into
// Define the socket file descriptor, the file file descriptor and the source variable
int sockfd;
FILE* file;
char* source = NULL;
int client_sock = 69;
// Handle the event of Ctrl+C being pressed
void handle_sigint(int sig) {
printf("SIGINT received, terminating gracefully.");
close(sockfd);
close(client_sock);
fclose(file);
free(source);
exit(0);
}
int main(int argc, char* argv[]) {
struct sockaddr_in servaddr = {};
// If there's less arguments than 3, we print the usage text.
if (argc < 3) {
printf("Usage:\n%s <port> <filename>\n", argv[0]);
exit(EXIT_FAILURE);
}
// Disable output buffering on stdout because it fucks with the output
setbuf(stdout, NULL);
// Create the socket and check that it went well
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
int port = atoi(argv[1]);
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
// Binding newly created socket to given IP and port
if (bind(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("Could not bind to address/port\n");
close(sockfd);
exit(EXIT_FAILURE);
}
// Now the server is ready to listen
// Listen on the socket
listen(sockfd, 1);
printf("Server listening on port %d\n", port);
// Open the file for reading
file = fopen(argv[2], "rb");
if (file == NULL) {
perror("Failed to open file");
close(sockfd);
exit(EXIT_FAILURE);
}
// Seek to the file's end and then reset the cursor(to find how big the file is)
fseek(file, 0L, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0L, SEEK_SET);
// Allocate memory for the file
source = malloc(fileSize);
if (source == NULL) {
printf("Error allocating memory for file...\n");
close(sockfd);
fclose(file);
exit(EXIT_FAILURE);
}
size_t numBytesRead = fread(source, sizeof(char), fileSize, file);
if (numBytesRead != fileSize) {
printf("Error reading file into memory...\n");
close(sockfd);
fclose(file);
free(source);
exit(EXIT_FAILURE);
}
// Register signal handler for SIGINT
signal(SIGINT, handle_sigint);
while (1) {
// funny way to check if the socket is open
if(client_sock != 69)
close(client_sock);
struct sockaddr_in client_addr;
socklen_t client_size = sizeof(client_addr);
// Accept the connection from the client and check if it went well
client_sock = accept(sockfd, (SA*)&client_addr, &client_size);
if (client_sock == -1) {
printf("Error accepting connection...\n");
continue;
}
// Print client's IP
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN);
printf("Connection attempt from %s\n");
char* sendbuf = source;
size_t remaining_bytes = fileSize;
size_t bytesSentSoFar = 0;
// Send the file in chunks.
while (remaining_bytes > 0) {
size_t chunk_size = (remaining_bytes < CHUNK_SIZE) ? remaining_bytes : CHUNK_SIZE;
ssize_t bytes_sent = send(client_sock, sendbuf, chunk_size, 0);
if (bytes_sent == -1) {
printf("Error sending file chunk...\n");
break;
}
bytesSentSoFar = fileSize - remaining_bytes;
printf("Sent %ld megabytes so far", bytesSentSoFar / 1000000);
printf("\r");
sendbuf += bytes_sent;
remaining_bytes -= bytes_sent;
}
printf("File sent to client %s.\n", client_ip);
// Close the client socket
close(client_sock);
}
// Close the server socket
close(sockfd);
// Close the file
fclose(file);
return 0;
}