Webserver/Client IPv4 und IPv6
Verfasst: Mi Jan 20, 2016 2:55 pm
Hallo zusammen,
hat einer von euch eine Idee, wie ich diesen Webserver in C so umschreiben kann, dass er nicht mehr nur mit IPv4 sondern als Dual Stack mit IPv4 und IPv6 läuft?
Webserver:
Client:
common.h:
Vielen Dank schonmal für euere Hilfe.
hat einer von euch eine Idee, wie ich diesen Webserver in C so umschreiben kann, dass er nicht mehr nur mit IPv4 sondern als Dual Stack mit IPv4 und IPv6 läuft?
Webserver:
Code: Alles auswählen
#include <alloca.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "common.h"
int main(int argc, char** argv) {
// Turn off output buffering so that we see all messages immediately
if (setvbuf(stdout, NULL, _IONBF, 0) != 0) {
perror("setvbuf failed!");
return 1;
}
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1) {
perror("Cannot create socket");
return 1;
}
struct sockaddr_in sa;
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(PORT);
if (bind(sock, (struct sockaddr *) &sa, sizeof sa) == -1) {
perror("bind failed!");
close(sock);
return 1;
}
for (;;) {
struct sockaddr_in peer;
socklen_t peer_len = sizeof peer;
char incoming[1+MAXSIZE];
ssize_t len = recvfrom(sock, incoming, sizeof incoming, 0, (struct sockaddr*) &peer, &peer_len);
if (len == -1) {
perror("recvfrom failed");
break;
}
char* peeraddr = inet_ntoa(peer.sin_addr);
assert(strlen(peeraddr) < MAXSIZE);
if (len <= 1) {
printf("Message from %s too short\n", peeraddr);
continue;
}
if (incoming[0] != 'M') {
printf("Weird first byte in message from %s: %i\n", peeraddr, (int) incoming[0]);
continue;
}
incoming[len-1] = '\0'; // Ensure that input is a valid C string
// Craft message contents
char* peername = incoming+1;
const char* hostname = get_hostname();
char msg[1+17+3*(MAXSIZE-1)+1];
size_t msglen = snprintf(msg, sizeof msg, "RHello %s (%s)! I am %s.", peername, peeraddr, hostname);
printf("Sending \"%s\" to %s\n", msg, peeraddr);
// Send response message
if (sendto(sock, msg, msglen+1, 0, (struct sockaddr*) &peer, peer_len) == -1) {
perror("Send failed");
break;
}
}
// An error occured
close(sock);
return 2;
}
Code: Alles auswählen
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include "common.h"
void contact(char* host) {
// Determine remote address
struct hostent *he = gethostbyname(host);
if (he == NULL) {
perror("gethostbyname failed");
return;
}
struct sockaddr_in sa;
memset(&sa, 0, sizeof sa);
memcpy(& (sa.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
sa.sin_port = htons(PORT);
// Create socket
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1) {
perror("socket creation failed");
return;
}
// Compose message
char sendbuf[1+MAXSIZE];
int msglen = snprintf(sendbuf, sizeof sendbuf, "M%s", get_hostname()) + 1;
// Configure socket timeouts
struct timeval timeout;
memset(&timeout, 0, sizeof timeout);
timeout.tv_sec = 1;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) == -1) {
perror("setsockopt(SO_RCVTIMEO) failed");
close(sock);
return;
}
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof timeout) == -1) {
perror("setsockopt(SO_SNDTIMEO) failed");
close(sock);
return;
}
// Send message
if (sendto(sock, sendbuf, msglen, 0, (struct sockaddr *) &sa, sizeof sa) == -1) {
perror("sendto failed");
close(sock);
return;
}
char recvbuf[4*MAXSIZE];
struct sockaddr_in peer;
socklen_t peer_len = sizeof peer;
size_t msgsize = recvfrom(sock, &recvbuf, sizeof recvbuf, 0, (struct sockaddr*) &peer, &peer_len);
if (msgsize == -1) {
if (errno == EWOULDBLOCK) {
fprintf(stderr, "No response from %s!\n", host);
close(sock);
return;
}
perror("recvfrom failed");
close(sock);
return;
}
recvbuf[msgsize-1] = '\0';
const char* peeraddr = inet_ntoa(sa.sin_addr);
if (recvbuf[0] != 'R') {
fprintf(stderr, "Reply from %s(%s) does not follow protocol!\n"
"Expected message type 'R', but got %c\n",
peeraddr, host, recvbuf[0]);
close(sock);
return;
}
printf("\"%s\" from %s (%s)\n", recvbuf+1, peeraddr, host);
close(sock);
}
int main(int argc, char** argv) {
if (argc == 1) {
fprintf(stderr, "No remote host given!\n");
printf("Usage: %s server-ip [server-ip..]\n", argv[0]);
return 1;
}
char** host = argv+1;
while (argc > 1) {
contact(*host);
host++;
argc--;
}
return 0;
}
Code: Alles auswählen
#define PORT 2673
// Maximum size of various string fields (including trailing \0)
#define MAXSIZE 256
/**
* Determines this machine's hostname, of up to MAXSIZE characters (including trailing \0).
* Returns a static buffer.
*/
extern const char* get_hostname();