-
Notifications
You must be signed in to change notification settings - Fork 0
/
tcpServerUtil.c
executable file
·115 lines (100 loc) · 3.9 KB
/
tcpServerUtil.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
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include "logger.h"
#include "addressUtility.h"
#define MAXPENDING 5 // Maximum outstanding connection requests
#define BUFSIZE 256
#define MAX_ADDR_BUFFER 128
static char addrBuffer[MAX_ADDR_BUFFER];
/*
** Se encarga de resolver el número de puerto para service (puede ser un string con el numero o el nombre del servicio)
** y crear el socket pasivo, para que escuche en cualquier IP, ya sea v4 o v6
*/
int setupTCPServerSocket(const char *service) {
// Construct the server address structure
struct addrinfo addrCriteria; // Criteria for address match
memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure
addrCriteria.ai_family = AF_UNSPEC; // Any address family
addrCriteria.ai_flags = AI_PASSIVE; // Accept on any address/port
addrCriteria.ai_socktype = SOCK_STREAM; // Only stream sockets
addrCriteria.ai_protocol = IPPROTO_TCP; // Only TCP protocol
struct addrinfo *servAddr; // List of server addresses
int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr);
if (rtnVal != 0) {
log(FATAL, "getaddrinfo() failed %s", gai_strerror(rtnVal));
return -1;
}
int servSock = -1;
// Intentamos ponernos a escuchar en alguno de los puertos asociados al servicio
// Iteramos por todas las Ips y hacemos el bind por alguna de ellas.
// Con esta implementación estaremos escuchando o bien en IPv4 o en IPv6, pero no en ambas
for (struct addrinfo *addr = servAddr; addr != NULL && servSock == -1; addr = addr->ai_next) {
// Create a TCP socket
servSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (servSock < 0)
continue; // Socket creation failed; try next address
// Bind to All the address and set socket to listen
if ((bind(servSock, addr->ai_addr, addr->ai_addrlen) == 0) && (listen(servSock, MAXPENDING) == 0)) {
// Print local address of socket
struct sockaddr_storage localAddr;
socklen_t addrSize = sizeof(localAddr);
if (getsockname(servSock, (struct sockaddr *) &localAddr, &addrSize) >= 0) {
printSocketAddress((struct sockaddr *) &localAddr, addrBuffer);
log(INFO, "Binding to %s", addrBuffer);
}
} else {
close(servSock); // Close and try again
servSock = -1;
}
}
freeaddrinfo(servAddr);
return servSock;
}
int acceptTCPConnection(int servSock) {
struct sockaddr_storage clntAddr; // Client address
// Set length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Wait for a client to connect
int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen);
if (clntSock < 0) {
log(FATAL, "accept() failed");
return -1;
}
// clntSock is connected to a client!
printSocketAddress((struct sockaddr *) &clntAddr, addrBuffer);
log(INFO, "Handling client %s", addrBuffer);
return clntSock;
}
int handleTCPClient(int clntSocket) {
char buffer[BUFSIZE]; // Buffer for echo string
// Receive message from client
ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0) {
log(ERROR, "recv() failed");
return -1; // TODO definir codigos de error
}
// Send received string and receive again until end of stream
while (numBytesRcvd > 0) { // 0 indicates end of stream
// Echo message back to client
ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);
if (numBytesSent < 0) {
log(ERROR, "send() failed");
return -1; // TODO definir codigos de error
}
else if (numBytesSent != numBytesRcvd) {
log(ERROR, "send() sent unexpected number of bytes ");
return -1; // TODO definir codigos de error
}
// See if there is more data to receive
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0) {
log(ERROR, "recv() failed");
return -1; // TODO definir codigos de error
}
}
close(clntSocket);
return 0;
}