[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends] バケツリレー[1/2]




  高橋です。
  TCP/IPのデータをバケツリレーするプログラムを書きました。
  名前は cocoa。

  図にするとこんな感じです。
    発信元  -------> 中継サーバー -------> 中継先サーバー ---> ?
      (A)   <-------   (cocoa)    <-------     (B)        <---

  一応ソース(200行程度)は載せますが、必要なヘッダとライブラリは
環境に応じて自分で考えてください。(^^;
  (注:socket と POSIX thread を使ってます)
  こちらでは、SolarisとLinuxでコンパイル & 動作確認を行いました。
  なお、終了させるための処理を書いてないので、自分でプロセスを殺
してください。(^^;

---- cocoa.c [1/2] ここから -------------------------
#define SD_RECEIVE      0x00
#define SD_SEND         0x01
#define SD_BOTH         0x02
 
static unsigned long server_addr;
static int           server_port;
static unsigned long proxy_addr;
static int           proxy_port;

typedef struct tagConnectData {
  int             client_socket;
  int             proxy_socket;
  pthread_mutex_t client_socket_mutex;
  pthread_mutex_t proxy_socket_mutex;
} ConnectData;

/* for DEBUG */
static int count = 0;
static pthread_mutex_t count_mutex;

static void cleanup_child_socket(ConnectData* p_connect_data)
{
  pthread_mutex_t* client_socket_mutex =
                       &(p_connect_data->client_socket_mutex);
  pthread_mutex_t* proxy_socket_mutex  =
                       &(p_connect_data->proxy_socket_mutex);
  int* client_socket = &(p_connect_data->client_socket);
  int* proxy_socket  = &(p_connect_data->proxy_socket);

  pthread_mutex_lock(client_socket_mutex);
  if( *client_socket != -1 )
  {
    shutdown(*client_socket, SD_BOTH);
    close(*client_socket);
    *client_socket = -1;
  }
  pthread_mutex_unlock(client_socket_mutex);

  pthread_mutex_lock(proxy_socket_mutex);
  if( *proxy_socket != -1 )
  {
    shutdown(*proxy_socket, SD_BOTH);
    close(*proxy_socket);
    *proxy_socket = -1;
  }
  pthread_mutex_unlock(proxy_socket_mutex);
}

static void* child_read_thread(void* p_connect_data)
{
  ConnectData* connect_data = (ConnectData*)p_connect_data;
  int client_socket = connect_data->client_socket;
  int proxy_socket  = connect_data->proxy_socket;
  unsigned char c;
  int recv_count;
  int send_count;
  for(;;)
  {
    recv_count = recv(client_socket, &c, 1, 0);
    if( recv_count != 1 )
      break;
    send_count = send(proxy_socket, &c, 1, 0);
    if( send_count != 1 )
      break;
  }
  cleanup_child_socket(connect_data);
}

static void* child_write_thread(void* p_connect_data)
{
  ConnectData* connect_data = (ConnectData*)p_connect_data;
  int client_socket = connect_data->client_socket;
  int proxy_socket  = connect_data->proxy_socket;
  unsigned char c;
  int recv_count;
  int send_count;

  for(;;)
  {
    recv_count = recv(proxy_socket, &c, 1, 0);
    if( recv_count != 1 )
      break;
    send_count = send(client_socket, &c, 1, 0);
    if( send_count != 1 )
      break;
  }
  cleanup_child_socket(connect_data);
}
---- cocoa.c [1/2] ここまで -------------------------

-- 
高橋智宏