ソケット通信によるネットワークデータ転送

ネットワーク上のデータを取得するには,サーバ・クライアント間でソケットを作成し通信を用います. 今回の例題では,クライアントから送られたメッセージをそのまま送り返すecho機能を持ったサーバと,そのサーバへアクセスするためのクライアントとして通信を行うためのソケットを生成する例です。

mytcpcl.c では単純にメッセージの送受信を行うのみですが,echo_cl.c では,ソケットの作成後,リダイレクションによりソケットをファイル記述子へ割り当て(fdopen_sock 関数),高水準入出力関数を利用して送受信を可能にしています.

ソースのダウンロード

サーバ側mytcpsv.c)
//-----------------------------------------------------------------
//  mytcpsv.c : 簡易TCP/IPサーバ [echo 機能]
//-----------------------------------------------------------------
#include <stdio.h>
#include <signal.h>
#include "tcp_lib.h"
//-----------------------------------------------------------------
void do_tcpsv(int port);
//-----------------------------------------------------------------
int main(int argc,char* argv[])
{
    int pid,port = 7;
    printf("\n<q Enter>: end of program\n\n");
    // echo サーバ用プロセスの開始
    if((pid = fork()) < 0){
        perror("fork"); exit(1);
    }
    if(pid == 0){
        do_tcpsv(port); exit(0);
    } else {
        // 終了コマンド
        while(getchar()!='q') ;
        // プロセスの強制終了
        kill(pid,SIGINT);
    }
    printf("end of TCP server.\n");
    return 0;
}

// 簡易TCPサーバ [echo 機能]
void do_tcpsv(int port)
{
    int acc,sock,sbyte;
    char clhost[256];
    BYTE recvcom[BUFSIZ];
    struct sigaction sa;
    void myendsv(int no) { // 終了用
        if(sock > 0) TCP_close(sock);
        exit(0);
    }
    // シグナルハンドラの設定
    memset(&sa,0,sizeof(struct sigaction));
    sa.sa_handler = myendsv;
    if(sigaction(SIGINT,&sa,NULL) != 0){
        perror("sigaction");
        return;
    }
    // サーバ起動
    if((acc = TCP_acc_port(port)) < 0)
        return;
    Disp_ipinfo("echo server",port);
    // echo サーバ
    sock = -1;
    while(1){
        sock = TCP_accept(acc,clhost);
        if(sock < 0){
            perror("accept"); continue;
        }
        // データ送受信[echo]
        printf("**new client: [%s]\n",clhost);
        while((sbyte = TCP_recv(sock,recvcom,0)) > 0){
            printf("recbuf = %s[%d byte]\n",(char*)recvcom,sbyte);
            TCP_send(sock,recvcom,sbyte);
        }
        printf("**client disconnected.\n");
        TCP_close(sock);
        sock = -1;
    }
    return;
}
実行結果
Gami[30]% ./mytcpsv.exe

<q Enter>: end of program

** echo server
  medlanc[219.61.76.47]: 7
**new client: [127.0.0.1] --> mytcpcl.exe からの接続
recbuf = send data.[10 byte]
**client disconnected.
**new client: [127.0.0.1] --> echo_cl.exe からの接続
recbuf = sending data.
[14 byte]
recbuf = test of echo server.
[21 byte]
recbuf = end of transmission.
[21 byte]
**client disconnected.
q
end of TCP server.
Gami[31]%
クライアント側mytcpcl.c)
//-----------------------------------------------------------------
//  mytcpcl.c:TCP/IP クライアント
//-----------------------------------------------------------------
#include <stdio.h>
#include "tcp_lib.h"

int main(int argc,char* argv[])
{
    int rbyte,sock,portno;
    char *server,recbuf[BUFSIZ];
    if(argc != 3) {
        printf("Usage: %s host port\n",argv[0]); return 0;
    }
    server = argv[1]; portno = atoi(argv[2]);
    // 通信開始
    if((sock = TCP_open(server,portno)) < 0){
        return 0;
    }
    // データの送信
    TCP_send(sock,"send data.",strlen("send data."));
    // 受信
    rbyte = TCP_recv(sock,recbuf,0);
    printf("received: [%s]\n",recbuf);
    // 通信終了
    TCP_close(sock);
    return 0;
}

実行結果
Gami[549]% ./mytcpcl.exe localhost 7
localhost: Connection refused  --> echo サーバの起動前
Gami[550]% ./mytcpcl.exe localhost 7
received: [send data.]
Gami[551]%

echoクライアント側echo_cl.c)
//-----------------------------------------------------------------
//  echo_cl.c : 文字列を送受信するクライアント
//-----------------------------------------------------------------
#include <stdio.h>
#include "tcp_lib.h"
//-----------------------------------------------------------------
int echo_client(char *server,int portno);
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
    int  portno;
    char *server;
    if(argc != 3) {
        fprintf(stdout,"Usage: %s host port\n",argv[0]);
        return 0;
    }
    server = argv[1];
    portno = atoi(argv[2]);
    echo_client(server,portno);
    return 0;
}
//-----------------------------------------------------------------
// echo クライアント
//-----------------------------------------------------------------
int echo_client(char *server, int portno)
{
    int sock;
    BYTE sbuf[BUFSIZ],rbuf[BUFSIZ];
    FILE *in,*out;
    // ソケット通信の開始
    if((sock = TCP_open(server,portno)) < 0) { exit(1); }
    // ソケットからファイル記述子への割当て
    if(fdopen_sock(sock,&in,&out) < 0) { exit(1); }
    // 通信内容
    printf("==> "); fflush(stdout);
    while(fgets(sbuf,BUFSIZ,stdin)) {
        fprintf(stdout,"sending: [%s]\n",sbuf);
        fprintf(out,"%s",sbuf);
        fgets(rbuf,BUFSIZ,in);
        printf("received: [%s]\n",rbuf);
        printf("==> "); fflush(stdout);
        strcpy(rbuf,"");
    }
    printf("\n");
    // 通信先のクローズ
    fclose(in);
    fclose(out);
    return 0;
}

実行結果
Gami[551]% ./echo_cl.exe localhost 7
==> sending data.
sending: [sending data.
]
received: [sending data.
]
==> test of echo server.
sending: [test of echo server.
]
received: [test of echo server.
]
==> end of transmission.
sending: [end of transmission.
]
received: [end of transmission.
]
==>
Gami[552]%

inserted by FC2 system