Tuesday, January 31, 2012

A tiny C library for client sockets

Sockets are everything in programming, especially, after the wide use of internet. Sockets are used for connecting two devices in a network using several low level protocols. At user level, those protocols are not transparent to user, that is, opening a connection and sending some string or binary data along a network is the whole thing for a general programmer.

Socket programming is not a difficult one in much of high level languages. I have used sockets in Java several times and the stuff were running like a charm. Unfortunately, same easiness is not current for C. However, it is the faster way of doing this work.

Last day, I needed to code a client socket for retrieving some data over the network. My Ubuntu was ready for the task with its installed C libraries. Since Linux sockets are a little bit detailed so there were too many terms (htons, inet_ntoa) which requires some low level knowledge of Linux sockets. For example, a C# programmer does not need to know how Windows converts an IP number to binary data and via versa. But Linux sockets are harder. But once you learn it, it is more fun.

Finally, I wrote a small library for a client socket task. The example of this code is shown below:

(Test.c)
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "ClientSocket.h"
  5.  
  6.  
  7. int main(int argc, char** argv) {
  8. /* We will store some text in this buffer */
  9. int bufsize=1024;
  10. char buffer[bufsize];
  11. char *hostname = "blogspot.com";
  12. int port = 80;
  13. /* Getting ip address of google.com into buffer */
  14. getIPAddress("google.com", buffer);
  15. printf("Connecting to (%s) %s\n", hostname, buffer);
  16. /* Creating socket */
  17. struct ClientSocket *socket = socket_create(buffer, port);
  18. /* Connecting */
  19. socket_connect(socket);
  20. /* Sending a http request */
  21. strcpy(buffer,"GET /\n\n");
  22. socket_send(socket, buffer, strlen(buffer));
  23. /* Receiving the first #bufsize elements */
  24. socket_receive(socket, buffer, bufsize);
  25. printf("%s",buffer);
  26. /* Do not read any more. Closing */
  27. socket_close(socket);
  28. return (EXIT_SUCCESS);
  29. }
  30.  
 



The header file of out tiny library is here:(ClientSocket.h)
  1. /*
  2. * File: ClientSocket.h
  3. * Author: Practical Code Solutions
  4. *
  5. * Created on January 31, 2012, 9:56 AM
  6. */
  7.  
  8. #ifndef CLIENTSOCKET_H
  9. #define CLIENTSOCKET_H
  10.  
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14.  
  15. struct ClientSocket {
  16. int fd;
  17. char *ip;
  18. int port;
  19. int (*getIp)(const char *, char *);
  20. };
  21.  
  22. int getIPAddress(const char *host, char *ip);
  23.  
  24. struct ClientSocket *socket_create(char *ip, int port);
  25.  
  26. int socket_connect(struct ClientSocket *sock);
  27.  
  28. int socket_send(struct ClientSocket *sock, char *data, int len);
  29.  
  30. int socket_receive(struct ClientSocket *sock, char *data, int len);
  31.  
  32. int socket_close(struct ClientSocket *sock);
  33.  
  34.  
  35.  
  36. #ifdef __cplusplus
  37. }
  38. #endif
  39.  
  40. #endif /* CLIENTSOCKET_H */
  41.  
The C source file of our tiny library is here: (ClientSocket.c)
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <arpa/inet.h>
  5. #include <sys/socket.h>
  6. #include <netdb.h>
  7.  
  8. #include "ClientSocket.h"
  9.  
  10. int getIPAddress(const char *host, char *ip){
  11. struct hostent *hh = gethostbyname(host);
  12. struct in_addr *add = hh->h_addr_list[0];
  13. strcpy(ip, inet_ntoa(add[0]));
  14. }
  15.  
  16. struct ClientSocket *socket_create(char *ip, int port){
  17. struct ClientSocket *socket = malloc(sizeof(struct ClientSocket));
  18. socket->ip = ip;
  19. socket->port = port;
  20. socket->getIp = getIPAddress;
  21. return(socket);
  22. }
  23.  
  24. int socket_connect(struct ClientSocket *sock){
  25. struct sockaddr_in addr;
  26. int result;
  27. sock->fd = socket(AF_INET, SOCK_STREAM, 0);
  28. memset((char *)&addr, 0, sizeof(addr));
  29. addr.sin_port = htons(sock->port);
  30. addr.sin_family = AF_INET;
  31. addr.sin_addr.s_addr = inet_addr(sock->ip);
  32. result = connect(sock->fd, (struct sockaddr *)&addr, sizeof(addr));
  33. return(result);
  34. }
  35.  
  36. int socket_send(struct ClientSocket *sock, char *data, int len){
  37. return send(sock->fd, data, len, 0);
  38. }
  39.  
  40. int socket_receive(struct ClientSocket *sock, char *data, int len){
  41. data[len-1] = '\0';
  42. return recv(sock->fd, (void *)data, len -1 , 0);
  43. }
  44.  
  45. int socket_close(struct ClientSocket *sock){
  46. return close (sock->;fd);
  47. }

2 comments:

Thanks