Sockets - Bidirectional Communication IPv4/6 (terminal version)
Posted 01-17-2013 at 08:54 PM by rainbowsally
Tags computer mad science, mc2, simple c, sockets
Sockets - Bidirectional Communication IPv4/6 (terminal version)
Today's features:
[Note the addresses in this and the previous sockets experiments (here http://www.linuxquestions.org/questi...example-35270/) are at your own computer. Nothing should go out onto the net at all. If you want to change the addresses or port numbers, they are defined at the top of the main() functions as strings.]
To run the server(s) you might just want to do something like:
(with the ampersand) and in your main terminal
. Same with the v4 set of files.
And hey! What do you think will happen if you run a v4 socket setup with a v6 one? Find out! :-)
Now let's just get to the nitty.
file: client_v4.c
purpose: source code
file: client_v6.c
purpose: source code
file: server_v4.c
purpose: source code
file: server_v6.c
purpose: source code
For the Makefile you're on your own unless you have mc2. It shouldn't be too hard to roll your own, but here's the mc2.def for this setup.
Run 'mc2 -init' to create the initial Makefile. After this 'make update' will add and remove sources as names change or files are added or removed.
This mc2.def is a type MULTI build. (See 'mc2 -help all')
file: mc2.def
purpose: Makefile generation
These last two blogs entries use blocking (stopping cpu) until there is input. That's mostly convenient in a terminal app. For a gui, where you need to avoid hanging the gui, you either need a separate thread, a mutex, and all kinds of complication like that, or to run in non-blocking mode.
The Computer Mad Science Team
:-)
Today's features:
- More fun with sockets.
- Bidirectional communication using IPv4 and IPv6 socket streams (sequential).
- Interactive. (Only interprets one command, but it's easily expandable.)
- Terminal version for broader usefulness.
[Note the addresses in this and the previous sockets experiments (here http://www.linuxquestions.org/questi...example-35270/) are at your own computer. Nothing should go out onto the net at all. If you want to change the addresses or port numbers, they are defined at the top of the main() functions as strings.]
To run the server(s) you might just want to do something like:
Code:
xterm -e server_v6 &
Code:
client_v6
And hey! What do you think will happen if you run a v4 socket setup with a v6 one? Find out! :-)
Now let's just get to the nitty.
file: client_v4.c
purpose: source code
Code:
/* client_v6.c * Based on files found at * www.cs.utah.edu/~swalton/listings/sockets/programs/index.html * * Copyright (c) 2001 Sean Walton and Macmillan Publishers. Use may be in * whole or in part in accordance to the General Public License (GPL). * * Modified by Rainbow Sally Copyright (c) 2013 Rainbow Sally GPL 3+ */ //Demonstrate IPv4 client read/write functions #include <stdio.h> #include <errno.h> #include <resolv.h> #include <sys/socket.h> #include <arpa/inet.h> #include <ctype.h> #include <stdarg.h> #include <ctype.h> // isdigit() #include <stdlib.h> // abort(), exit(), atoi() #include <string.h> // strcmp(), memset() #include <unistd.h> // close() #define bzero(mem, len) memset(mem, 0, len) void panic(char* msg, ...) { va_list ap; va_start(ap, msg); vprintf(msg, ap); va_end(ap); abort(); } // MSG_OOB // MSG_PEEK // MSG_DONTROUTE #define MSG_FLAGS 0 /* default */ int main(int argc, char **argv) { const char* addr_str = "127.0.0.1"; const char* port_str = "9999"; printf( "Using address '%s', port %s\n" "Type text to send to server, 'bye' to end\n" , addr_str, port_str ); int sd, portnum; struct sockaddr_in addr; char line[100]; if(!sscanf(port_str, "%d", &portnum)) panic("portnum"); bzero(&addr, sizeof(addr)); if ( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) panic("socket"); addr.sin_family = AF_INET; addr.sin_port = htons(portnum); if ( inet_pton(AF_INET, addr_str, &addr.sin_addr) == 0 ) panic("inet_aton"); if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) panic("connect"); do { fgets(line, sizeof(line), stdin); send(sd, line, strlen(line)+1, MSG_FLAGS); recv(sd, line, sizeof(line), 0); printf("client recieved echo: %s", line); }while ( strcmp(line, "bye\n") != 0 ); close(sd); return 0; }
file: client_v6.c
purpose: source code
Code:
/* client_v6.c * Based on files found at * www.cs.utah.edu/~swalton/listings/sockets/programs/index.html * * Copyright (c) 2001 Sean Walton and Macmillan Publishers. Use may be in * whole or in part in accordance to the General Public License (GPL). * * Modified by Rainbow Sally Copyright (c) 2013 Rainbow Sally GPL 3+ */ // Demonstrate IPv6 client connection #include <stdio.h> #include <errno.h> #include <resolv.h> #include <sys/socket.h> #include <arpa/inet.h> #include <ctype.h> #include <stdarg.h> #include <ctype.h> // isdigit() #include <stdlib.h> // abort(), exit(), atoi() #include <string.h> // strcmp(), memset() #include <unistd.h> // close() #define bzero(mem, len) memset(mem, 0, len) void panic(char* msg, ...) { va_list ap; va_start(ap, msg); vprintf(msg, ap); va_end(ap); abort(); } // MSG_OOB // MSG_PEEK // MSG_DONTROUTE #define MSG_FLAGS 0 /* default */ int main(int count, char *strings[]) { const char* addr_str = "0::0"; const char* port_str = "9999"; printf( "Using address '%s', port %s\n" "Type text to send to server, 'bye' to end\n" , addr_str, port_str ); int sd, portnum; struct sockaddr_in6 addr; char line[100]; if(!sscanf(port_str, "%d", &portnum)) panic("portnum"); bzero(&addr, sizeof(addr)); if ( (sd = socket(PF_INET6, SOCK_STREAM, 0)) < 0 ) panic("socket"); addr.sin6_family = AF_INET6; addr.sin6_port = htons(portnum); if ( inet_pton(AF_INET6, addr_str, &addr.sin6_addr) == 0 ) panic("inet_aton"); if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) panic("connect6"); do { fgets(line, sizeof(line), stdin); send(sd, line, strlen(line)+1, MSG_FLAGS); recv(sd, line, sizeof(line), 0); printf("client recieved echo: %s", line); }while ( strcmp(line, "bye\n") != 0 ); close(sd); return 0; }
file: server_v4.c
purpose: source code
Code:
/* server_v6.c * Based on files found at * www.cs.utah.edu/~swalton/listings/sockets/programs/index.html * * Copyright (c) 2001 Sean Walton and Macmillan Publishers. Use may be in * whole or in part in accordance to the General Public License (GPL). * * Modified by Rainbow Sally Copyright (c) 2013 Rainbow Sally GPL 3+ */ //Demonstrate IPv4 server read/write functions #include <stdio.h> #include <errno.h> #include <resolv.h> #include <sys/socket.h> #include <arpa/inet.h> #include <ctype.h> #include <stdarg.h> #include <ctype.h> // isdigit() #include <stdlib.h> // abort(), exit(), atoi() #include <string.h> // strcmp(), memset() #include <arpa/inet.h> // inet_addr, etc. #include <unistd.h> // close() #define bzero(mem, len) memset(mem, 0, len) void panic(char* msg, ...) { va_list ap; va_start(ap, msg); vprintf(msg, ap); va_end(ap); abort(); } int main(int count, char *strings[]) { const char* port_str = "9999"; const char* addr_str = "127.0.0.1"; // localhost printf( "Using address '%s', port %s\n" "Waits for connection then echos string typed in client to\n" "stdout.\n" "Press Ctrl-C to exit\n", addr_str, port_str ); int sd, portnum; int max_conns = 15; // max number of simultaneous connections struct sockaddr_in addr; bzero(&addr, sizeof(addr)); if(!sscanf(port_str, "%d", &portnum)) panic("portnum"); if ( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) panic("socket"); addr.sin_family = AF_INET; addr.sin_port = htons(portnum); if ( inet_pton(AF_INET, addr_str, &addr.sin_addr) == 0 ) panic("inet_pton"); if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) panic("bind"); if ( listen(sd, max_conns) != 0 ) panic("listen"); while (1) { int sent; size_t size=sizeof(addr); int client; char line[100]; client = accept(sd, (struct sockaddr*)&addr, &size); fprintf(stderr, "Connected: %s port=%d\n", inet_ntop(AF_INET, &addr.sin_addr, line, sizeof(line)), addr.sin_port); for(;;) { // receive and echo back sent = send(client, line, recv(client, line, sizeof(line), 0), 0); if(sent == 0) // client disconnected break; fprintf(stderr, "server echoing: %s", line); if(strcmp(line, "bye\n") == 0) break; } close(client); } }
file: server_v6.c
purpose: source code
Code:
/* server_v6.c * Based on files found at * www.cs.utah.edu/~swalton/listings/sockets/programs/index.html * * Copyright (c) 2001 Sean Walton and Macmillan Publishers. Use may be in * whole or in part in accordance to the General Public License (GPL). * * Modified by Rainbow Sally Copyright (c) 2013 Rainbow Sally GPL 3+ */ //Demonstrate IPv6 server read/write functions #include <stdio.h> #include <errno.h> #include <resolv.h> #include <sys/socket.h> #include <arpa/inet.h> #include <ctype.h> #include <stdarg.h> #include <ctype.h> // isdigit() #include <stdlib.h> // abort(), exit(), atoi() #include <string.h> // strcmp(), memset() #include <arpa/inet.h> // inet_addr, etc. #include <unistd.h> // close() #define bzero(mem, len) memset(mem, 0, len) void panic(char* msg, ...) { va_list ap; va_start(ap, msg); vprintf(msg, ap); va_end(ap); abort(); } int main(int argc, char **argv) { const char* port_str = "9999"; const char* addr_str = "0::0"; printf( "Using address '%s', port %s\n" "Waits for connection then echos string typed in client to\n" "stdout.\n" "Press Ctrl-C to exit\n", addr_str, port_str ); int sd, portnum; struct sockaddr_in6 addr; bzero(&addr, sizeof(addr)); if(!sscanf(port_str, "%d", &portnum)) panic("portnum"); if ( (sd = socket(PF_INET6, SOCK_STREAM, 0)) < 0 ) panic("socket"); addr.sin6_family = AF_INET6; addr.sin6_port = htons(portnum); if ( inet_pton(AF_INET6, "0::0", &addr.sin6_addr) == 0 ) panic("inet_pton"); if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) panic("bind6"); if ( listen(sd, 15) != 0 ) panic("listen6"); while (1) { int sent; size_t size=sizeof(addr); int client; char line[100]; client = accept(sd, (struct sockaddr*)&addr, &size); fprintf(stderr, "Connected: %s port=%d\n", inet_ntop(AF_INET6, &addr.sin6_addr, line, sizeof(line)), addr.sin6_port); for(;;) { // receive and echo back sent = send(client, line, recv(client, line, sizeof(line), 0), 0); if(sent == 0) // client disconnected break; fprintf(stderr, "server echoing: %s", line); if(strcmp(line, "bye\n") == 0) break; } close(client); } }
For the Makefile you're on your own unless you have mc2. It shouldn't be too hard to roll your own, but here's the mc2.def for this setup.
Run 'mc2 -init' to create the initial Makefile. After this 'make update' will add and remove sources as names change or files are added or removed.
This mc2.def is a type MULTI build. (See 'mc2 -help all')
file: mc2.def
purpose: Makefile generation
Code:
# mc2.def template created with Makefile Creator 'mc2' # sandbox path and other new variables PREFIX = $(HOME)/usr32 BUILDDIR := $(PWD) OUTNAME = MULTI SRCDIR = . OBJDIR = o BINDIR = . # compile function overrides COMPILE = gcc -m32 -c -o # COMPILE <output_file> (for C, 32 bit, object) CFLAGS = -Wall -g3 # debug # CFLAGS = -Wall -O2 # optimized INCLUDE = -I $(SRCDIR) -I$(PREFIX)/include -I /usr/include # link function overrides LINK = gcc -m32 -o LDFLAGS = LIB = -L$(PREFIX)/lib -L/usr/lib semiclean: @rm -f $(OBJ) @rm -f *~ */*~ */*/*~ */*/*/*~ strip: @strip $(MAIN) @make semiclean # additional targets #mc2-update: # @mc2 -update clean: @rm -f $(MAIN) @rm -f $(OBJ) @rm -f *.kdevelop.pcs *.kdevses @rm -f *~ */*~ */*/*~ */*/*/*~ force: # used to force execution
The Computer Mad Science Team
:-)
Total Comments 0