From 669961023f3b4cfddf60d0ec49270a4d2d6f9889 Mon Sep 17 00:00:00 2001 From: Dylan Lloyd Date: Sun, 29 Jan 2012 12:15:11 -0500 Subject: [PATCH] init --- client.c | 94 ++++++++++++++++++++++++++++++++++++++++ server.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 client.c create mode 100644 server.c diff --git a/client.c b/client.c new file mode 100644 index 0000000..b494807 --- /dev/null +++ b/client.c @@ -0,0 +1,94 @@ +/* +** client.c -- a stream socket client demo +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PORT "3490" // the port client will be connecting to + +#define MAXDATASIZE 100 // max number of bytes we can get at once + +// get sockaddr, IPv4 or IPv6: +void *get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +int main(int argc, char *argv[]) +{ + int sockfd, numbytes; + char buf[MAXDATASIZE]; + struct addrinfo hints, *servinfo, *p; + int rv; + char s[INET6_ADDRSTRLEN]; + + if (argc != 2) { + fprintf(stderr,"usage: client hostname\n"); + exit(1); + } + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + return 1; + } + + // loop through all the results and connect to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + perror("client: socket"); + continue; + } + + if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + perror("client: connect"); + continue; + } + + break; + } + + if (p == NULL) { + fprintf(stderr, "client: failed to connect\n"); + return 2; + } + + inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), + s, sizeof s); + printf("client: connecting to %s\n", s); + + freeaddrinfo(servinfo); // all done with this structure + + if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { + perror("recv"); + exit(1); + } + + buf[numbytes] = '\0'; + + printf("client: received '%s'\n",buf); + + close(sockfd); + + return 0; +} + diff --git a/server.c b/server.c new file mode 100644 index 0000000..74cf914 --- /dev/null +++ b/server.c @@ -0,0 +1,128 @@ +/* +** server.c -- a stream socket server demo +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PORT "3490" // the port users will be connecting to + +#define BACKLOG 10 // how many pending connections queue will hold + +void sigchld_handler(int s) +{ + while(waitpid(-1, NULL, WNOHANG) > 0); +} + +// get sockaddr, IPv4 or IPv6: +void *get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +int main(void) +{ + int sockfd, new_fd; // listen on sock_fd, new connection on new_fd + struct addrinfo hints, *servinfo, *p; + struct sockaddr_storage their_addr; // connector's address information + socklen_t sin_size; + struct sigaction sa; + int yes=1; + char s[INET6_ADDRSTRLEN]; + int rv; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; // use my IP + + if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + return 1; + } + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + perror("server: socket"); + continue; + } + + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(int)) == -1) { + perror("setsockopt"); + exit(1); + } + + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + perror("server: bind"); + continue; + } + + break; + } + + if (p == NULL) { + fprintf(stderr, "server: failed to bind\n"); + return 2; + } + + freeaddrinfo(servinfo); // all done with this structure + + if (listen(sockfd, BACKLOG) == -1) { + perror("listen"); + exit(1); + } + + sa.sa_handler = sigchld_handler; // reap all dead processes + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + printf("server: waiting for connections...\n"); + + while(1) { // main accept() loop + sin_size = sizeof their_addr; + new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); + if (new_fd == -1) { + perror("accept"); + continue; + } + + inet_ntop(their_addr.ss_family, + get_in_addr((struct sockaddr *)&their_addr), + s, sizeof s); + printf("server: got connection from %s\n", s); + + if (!fork()) { // this is the child process + close(sockfd); // child doesn't need the listener + if (send(new_fd, "Hello, world!", 13, 0) == -1) + perror("send"); + close(new_fd); + exit(0); + } + close(new_fd); // parent doesn't need this + } + + return 0; +} + -- 2.30.2