⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 echoserver-unix.c

📁 GNet是一个简单的网络库。它是目标定向的
💻 C
字号:
/* Unix socket Echo server * Copyright (C) 2001  Mark Ferlatte * Adapted from echoserver.c, Copyright (C) 2000  David Helder * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <glib.h>#define GNET_EXPERIMENTAL 1#include <gnet.h>	/* Or <gnet/gnet.h> when installed. */typedef enum { NORMAL, ASYNC} ServerType;void cleanup_on_sig(int signum);static void usage(int status);static void normal_echoserver(gchar *path);static void async_echoserver(gchar *path);GUnixSocket *server;intmain(int argc, char** argv){  gchar *path = NULL;  ServerType server_type = NORMAL;	  gnet_init ();  if (argc !=  2 && argc != 3) {    usage(EXIT_FAILURE);  }  if (argc == 3) {    if (strcmp(argv[1], "--async") == 0)      server_type = ASYNC;    else {      usage(EXIT_FAILURE);    }  }	  path = g_new0(gchar, strlen(argv[argc - 1]));  path = memcpy(path, argv[argc - 1], strlen(argv[argc - 1]));  signal(SIGINT, cleanup_on_sig);  signal(SIGTERM, cleanup_on_sig);		  switch (server_type) {  case NORMAL:    g_print("Normal echo server running\n");    normal_echoserver(path);    break;  case ASYNC:    g_print("Async echo server running\n");    async_echoserver(path);    break;  default:    g_assert_not_reached();  }  return 0;}static voidusage(int status){  g_print("usage: echoserver-unix [(nothing)|--async] <path>\n");  exit(status);}voidcleanup_on_sig(int signum){  gnet_unix_socket_delete(server);  exit(EXIT_SUCCESS);}static voidnormal_echoserver(gchar *path){  GUnixSocket *client = NULL;  gchar buffer[1024];  guint n;  GIOChannel *ioclient = NULL;  GIOError e;  g_assert(path != NULL);	  /* Create the server */  server = gnet_unix_socket_server_new(path);  g_assert(server != NULL);  while ((client = gnet_unix_socket_server_accept(server)) != NULL) {    ioclient = gnet_unix_socket_get_iochannel(client);    g_assert(ioclient != NULL);    while ((e = gnet_io_channel_readline(ioclient, buffer,					 sizeof(buffer), &n))	   == G_IO_ERROR_NONE && (n > 0)) {      e = gnet_io_channel_writen(ioclient, buffer, n, &n);      if (e != G_IO_ERROR_NONE)	break;      fwrite(buffer, n, 1, stdout);    }    if (e != G_IO_ERROR_NONE)      fprintf(stderr,	      "\nRecieved error %d (closing socket).\n",	      e);    g_io_channel_unref(ioclient);    gnet_unix_socket_delete(client);  }}typedef struct{  GUnixSocket *socket;  GIOChannel *iochannel;  guint out_watch;  gchar buffer[1024];  guint n;} client_state;static void clientstate_delete(client_state *state);static gboolean async_server_iofunc(GIOChannel *server,				    GIOCondition c, gpointer data);static gboolean async_client_iofunc(GIOChannel *client,				    GIOCondition c, gpointer data);static voidclientstate_delete(client_state *state){  if (state->out_watch)    g_source_remove(state->out_watch);  g_io_channel_unref(state->iochannel);  gnet_unix_socket_delete(state->socket);  g_free(state);}static voidasync_echoserver(gchar *path){  GIOChannel *iochannel = NULL;  GMainLoop *main_loop = NULL;  g_assert(path != NULL);  server = gnet_unix_socket_server_new(path);  g_assert(server != NULL);  main_loop = g_main_new(FALSE);  /* Add a watch for incoming clients */  iochannel = gnet_unix_socket_get_iochannel(server);  g_io_add_watch(iochannel,		 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,		 async_server_iofunc, server);  /* Start the main loop */  g_main_run(main_loop);}static gbooleanasync_server_iofunc(GIOChannel *iochannel, GIOCondition c, gpointer data){  GUnixSocket *server = (GUnixSocket *) data;  g_assert(server != NULL);  if (c & G_IO_IN) {    GUnixSocket *client = NULL;    GIOChannel *client_iochannel = NULL;    client_state *cs = NULL;    client = gnet_unix_socket_server_accept(server);    g_assert(client != NULL);    client_iochannel = gnet_unix_socket_get_iochannel(client);    g_assert(client_iochannel != NULL);    cs = g_new0(client_state, 1);    cs->socket = client;    cs->iochannel = client_iochannel;    g_io_add_watch(client_iochannel,		   G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,		   async_client_iofunc, cs);  } else {    fprintf(stderr, "Server error %d\n", c);    return FALSE;  }  return TRUE;}/*  This callback is called for (IN|ERR) or OUT.    We add the watch for (IN|ERR) when the client connects in  async_server_iofunc().  We remove it if the connection is closed  (i.e. we read 0 bytes) or if there's an error.  We add the watch for OUT when we have something to write and remove  it when we're done writing or when the connection is closed. */static gbooleanasync_client_iofunc(GIOChannel *iochannel, GIOCondition c,		    gpointer data){  client_state *cs = (client_state *) data;  g_assert(cs != NULL);  /* Check for socket error */  if (c & G_IO_ERR) {    fprintf(stderr, "Client socket error!\n");    goto error;  }  /* Check for data to be read (or if the socket was closed) */  if (c & G_IO_IN) {    GIOError e;    guint bytes_read;    /* Read the data into our buffer */    e = g_io_channel_read(iochannel,			  &cs->buffer[cs->n],			  sizeof(cs->buffer) - cs->n,			  &bytes_read);    /* Check for socket error */    if (e != G_IO_ERROR_NONE) {      fprintf(stderr, "Client read error: %d\n", e);      goto error;    } else if (bytes_read == 0) {      /* Check if we read 0 bytes, which means the connection	 is closed */      goto error;    } else {      g_assert(bytes_read > 0);      /* If there isn't an out_watch, add one */      if (cs->out_watch == 0) {	cs->out_watch =	  g_io_add_watch(iochannel,			 G_IO_OUT,			 async_client_iofunc,			 cs);      }      fwrite(&cs->buffer[cs->n], bytes_read, 1, stdout);      cs->n += bytes_read;    }  }  if (c & G_IO_OUT) {    GIOError e;    guint bytes_written;    /* Write the data out */    e = g_io_channel_write(iochannel, cs->buffer, cs->n,			   &bytes_written);    if (e != G_IO_ERROR_NONE) {      fprintf(stderr, "Client write error: %d\n", e);      clientstate_delete(cs);      return FALSE;    } else if (bytes_written > 0) {      /* Move the memory down some (you wouldn't do this	 in a performance server because it's slow) */      g_memmove(cs->buffer,		&cs->buffer[bytes_written],		bytes_written);      cs->n -= bytes_written;    }    /* Check if done */    if (cs->n == 0) {      cs->out_watch = 0;      return FALSE;    }  }  return TRUE; error:  clientstate_delete(cs);  return FALSE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -