Signed-off-by: Angus Salkeld asalkeld@redhat.com --- examples/.gitignore | 2 + examples/Makefile.am | 11 +++- examples/tcpclient.c | 74 ++++++++++++++++++++++++ examples/tcpserver.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 1 deletions(-) create mode 100644 examples/tcpclient.c create mode 100644 examples/tcpserver.c
diff --git a/examples/.gitignore b/examples/.gitignore index 097ac67..861a32c 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1 +1,3 @@ simplelog +tcpclient +tcpserver diff --git a/examples/Makefile.am b/examples/Makefile.am index 2b7cad8..867f9d8 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -21,8 +21,17 @@ MAINTAINERCLEANFILES = Makefiles.in EXTRA_DIST = CLEANFILES =
-noinst_PROGRAMS = simplelog +noinst_PROGRAMS = simplelog tcpclient tcpserver
simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include simplelog_LDADD = -lrt $(top_builddir)/lib/libqb.la + +tcpclient_SOURCES = tcpclient.c $(top_builddir)/include/qb/qbloop.h +tcpclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +tcpclient_LDADD = -lrt $(top_builddir)/lib/libqb.la + +tcpserver_SOURCES = tcpserver.c $(top_builddir)/include/qb/qbloop.h +tcpserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include +tcpserver_LDADD = -lrt $(top_builddir)/lib/libqb.la + diff --git a/examples/tcpclient.c b/examples/tcpclient.c new file mode 100644 index 0000000..8283321 --- /dev/null +++ b/examples/tcpclient.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" +#include <netdb.h> + + +int +main(int argc, char *argv[]) +{ + int sock; + int32_t res; + char send_data[1024]; + char recv_data[1024]; + struct sockaddr_in server_addr; + struct hostent *host = gethostbyname("127.0.0.1"); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("Socket"); + exit(1); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(5000); + server_addr.sin_addr = *((struct in_addr *)host->h_addr); + bzero(&(server_addr.sin_zero),8); + + if (connect(sock, (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) { + perror("Connect"); + exit(1); + } + + while(1) { + printf("\nSEND (q or Q to quit) : "); + if (gets(send_data) == NULL) { + continue; + } + + if (strcmp(send_data , "q") != 0 && + strcmp(send_data , "Q") != 0) { + res = send(sock, send_data, strlen(send_data), 0); + } else { + send(sock,send_data, strlen(send_data), 0); + close(sock); + break; + } + + if (res > 0) { + res = recv(sock, recv_data, 1024, 0); + recv_data[res] = '\0'; + + printf("\nResponse: %s ", recv_data); + } + } + return EXIT_SUCCESS; +} diff --git a/examples/tcpserver.c b/examples/tcpserver.c new file mode 100644 index 0000000..fddaa39 --- /dev/null +++ b/examples/tcpserver.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" + +#include <netdb.h> +#include <arpa/inet.h> +#include <poll.h> + +#include <qb/qbdefs.h> +#include <qb/qbloop.h> + +static int32_t +sock_read_fn(int32_t fd, int32_t revents, void *data) +{ + char recv_data[1024]; + char send_data[1024]; + int bytes_recieved; + + if (revents & POLLHUP) { + printf("Socket %d peer closed\n", fd); + close(fd); + return QB_FALSE; + } + + bytes_recieved = recv(fd, recv_data, 1024, 0); + if (bytes_recieved < 0) { + perror("recv"); + return QB_TRUE; + } + recv_data[bytes_recieved] = '\0'; + + if (strcmp(recv_data, "q") == 0 || + strcmp(recv_data, "Q") == 0) { + printf("Quiting connection from socket %d\n", fd); + close(fd); + return QB_FALSE; + } else { + printf("Recieved: %s\n", recv_data); + snprintf(send_data, 1024, "ACK %d bytes", bytes_recieved); + send(fd, send_data, strlen(send_data), 0); + } + return QB_TRUE; +} + +static int32_t +sock_accept_fn(int32_t fd, int32_t revents, void *data) +{ + struct sockaddr_in client_addr; + qb_loop_t * ml = (qb_loop_t*)data; + socklen_t sin_size = sizeof(struct sockaddr_in); + int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size); + + if (connected < 0) { + perror("accept"); + return QB_TRUE; + } + printf("I got a connection from (%s , %d)\n", + inet_ntoa(client_addr.sin_addr), + ntohs(client_addr.sin_port)); + + qb_loop_poll_add(ml, QB_LOOP_MED, + connected, POLLIN, + ml, sock_read_fn); + + return QB_TRUE; +} + +static int32_t +please_exit_fn(int32_t rsignal, void *data) +{ + qb_loop_t * ml = (qb_loop_t*)data; + + printf("Shutting down at you request...\n"); + qb_loop_stop(ml); + return QB_FALSE; +} + +int +main(int argc, char *argv[]) +{ + int sock; + int true_opt = 1; + struct sockaddr_in server_addr; + qb_loop_t * ml = qb_loop_create(); + + if ((sock = socket(AF_INET, + SOCK_STREAM, + 0)) == -1) { + perror("Socket"); + exit(1); + } + + if (setsockopt(sock, + SOL_SOCKET, + SO_REUSEADDR, + &true_opt, + sizeof(int)) == -1) { + perror("Setsockopt"); + exit(1); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(5000); + server_addr.sin_addr.s_addr = INADDR_ANY; + bzero(&(server_addr.sin_zero),8); + + printf("TCPServer binding to port 5000\n"); + if (bind(sock, + (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) { + perror("Unable to bind"); + exit(1); + } + + printf("TCPServer Waiting for client on port 5000\n"); + + if (listen(sock, 5) == -1) { + perror("Listen"); + exit(1); + } + + qb_loop_poll_add(ml, QB_LOOP_MED, + sock, POLLIN, + ml, sock_accept_fn); + + qb_loop_signal_add(ml, QB_LOOP_HIGH, + SIGINT, + ml, please_exit_fn, + NULL); + qb_loop_run(ml); + + close(sock); + return 0; +}