Skeleton TCP routines using Glib.
Language: English
Programming Language: C
Published by: centove [not registered]
Last Update: 5/15/2006
Views: 738
Description
This is a basic skeleton of functions that utilize the GIOChannel stuff from glib for a basic tcp server. This will open a socket and do all the work needed for accepting connections and setting up appropriate callbacks. Hook into it at the tcp client_activity section.Call tcp_socket_init (port #) to get everything set up.
Code
1 /*
2 * $Id: $
3 *
4 * TCP Service -- Handles all socket level issues.
5 */
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include <glib.h>
11 #include <errno.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <fcntl.h>
16
17 /****************************************************************************
18 * Forward references
19 ***************************************************************************/
20 gboolean tcp_new_connection (GIOChannel *source,
21 GIOCondition condition,
22 gpointer data);
23 gboolean tcp_client_activity (GIOChannel *source,
24 GIOCondition condition,
25 gpointer data);
26 /****************************************************************************
27 * Implementation.
28 ***************************************************************************/
29 void
30 tcp_enable_reuseaddr (gint sock)
31 {
32 gint tmp = 1;
33 if (sock < 0)
34 return;
35 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (gchar *)&tmp,
36 sizeof (tmp)) == -1)
37 perror ("Bah! Bad setsockopt ()\n");
38 }
39
40 void
41 tcp_enable_nbio (gint fd)
42 {
43 if (fcntl (fd, F_SETOWN, getpid()) == -1)
44 perror ("fcntl (F_SETOWN) error\n");
45 if (fcntl (fd, F_SETFL, FNDELAY) == -1)
46 perror ("fcntl (F_SETFL, FNDELAY\n");
47 }
48
49 void
50 tcp_socket_init (gint port)
51 {
52 gint s;
53 struct sockaddr_in addr;
54 GIOChannel *channel;
55
56 if (port <= 0)
57 return ;
58
59 s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
60 if (s == -1)
61 return;
62 tcp_enable_reuseaddr (s);
63 memset (&addr, 0, sizeof (addr));
64 addr.sin_family = AF_INET;
65 addr.sin_port = htons ((u_short)port);
66 addr.sin_addr.s_addr = INADDR_ANY;
67 if (bind (s, (struct sockaddr *)&addr, sizeof (addr)) == -1)
68 {
69 close (s);
70 return ;
71 }
72 if (listen (s, 5) == -1)
73 {
74 close (s);
75 return ;
76 }
77 channel = g_io_channel_unix_new (s);
78 g_io_add_watch (channel, G_IO_IN, tcp_new_connection, NULL);
79 }
80
81 /****************************************************************************
82 * Callback functions
83 ***************************************************************************/
84 /**
85 * tcp_new_connection
86 * Will accept a new connection and add the client to the list of clients.
87 * actual client communication is handled elsewhere.
88 **/
89 gboolean
90 tcp_new_connection (GIOChannel *source, GIOCondition cond, gpointer data)
91 {
92 gint new; /* new socket descriptor */
93 gint client;
94 GIOChannel *new_channel;
95 struct sockaddr_in client_addr;
96
97 if (cond == G_IO_IN)
98 {
99 if ( (new = accept (g_io_channel_unix_get_fd (source),
100 (struct sockaddr *)&client_addr, &client)) < 0)
101 {
102 g_warning ("Unable to accept new connection.");
103 return FALSE;
104 }
105 new_channel = g_io_channel_unix_new (new);
106 g_io_add_watch (new_channel, G_IO_IN | G_IO_HUP, tcp_client_activity,
107 NULL);
108 }
109 return TRUE;
110 }
111
112 /**
113 * tcp_client_activity
114 * Handles input from the clients and passes it off to the parser/dispatcher.
115 * This will get the raw data from the socket, make sure there is a NULL
116 * terminator, and call the command dispatcher.
117 * If the client has disconnected (condition G_IO_HUP), close the channel and remove
118 * this callback by returning FALSE.
119 **/
120 gboolean
121 tcp_client_activity (GIOChannel *source, GIOCondition cond, gpointer data)
122 {
123 gchar buf[1024];
124 guint num_read = 0;
125
126 if (cond == G_IO_IN)
127 {
128 g_print ("Read channel...\n");
129 if (g_io_channel_read (source, buf, sizeof (buf), &num_read) == G_IO_ERROR_NONE)
130 {
131 buf[num_read] = '\0'; /* Make sure its null terminated */
132
133 g_print ("Read (%d)\"%s\" from the socket\n", num_read, buf);
134 }
135 }
136 else if (cond == G_IO_HUP)
137 {
138 g_print ("Connection lost.\n");
139 g_io_channel_close(source);
140 return FALSE;
141 }
142
143 return TRUE;
144 }
145
No comments avaiable
Add a comment
Name *
Email (won't be displayed) *
Website
Comment *
Security Code *