サンプル集  >  LinuxC  >  通信(サーバー側A)
通信(サーバー側A)
2013/11/25

>> 通信(クライアント側) からの続き

通信プログラムのサーバー側に、0バイトメッセージの送信を追加しました。

◆環境
OS Linux obsax3 3.0.6 #1 SMP Fri Nov 16 11:53:45 JST 2012 armv7l GNU/Linux
gcc 4.4.5 (Debian 4.4.5-8)

処理番号 2に0バイトメッセージの送信を追加しました。

LC114Server.c
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "outputLog.h"

int main()
{
    outputLog( "SV""LC114Server START\n" );

    int srcSocket;    // 自分
    int dstSocket;    // 相手

    struct sockaddr_in srcAddr;
    struct sockaddr_in dstAddr;
    socklen_t dstAddrSize = sizeof( dstAddr );

    int  iRet;
    char pcBuf[256];

    // sockaddr_in 構造体のセット
    bzero( ( char* )&srcAddr, sizeof( srcAddr ) );
    srcAddr.sin_port        = htons( 9876 );
    srcAddr.sin_family      = AF_INET;
    srcAddr.sin_addr.s_addr = INADDR_ANY;

    // ソケットの生成(ストリーム型)
    srcSocket = socket( AF_INET, SOCK_STREAM, 0 );
    if ( srcSocket < 0 )
    {
        perror( "socket" );
        return( -1 );
    }

    // アドレス使用中エラーを回避する
    // これをしないと2回目のbindでエラーになる。
    // socketはclose後も2〜4分残る模様
    int on = 1;
    iRet = setsockopt( srcSocket
                     , SOL_SOCKET
                     , SO_REUSEADDR
                     , &on
                     , sizeof( on )
                     );
    if ( iRet < 0 )
    {
        perror( "setsockopt" );
        return( -2 );
    }

    // ソケットのバインド
    iRet = bind( srcSocket
               , ( struct sockaddr* )&srcAddr
               , sizeof( srcAddr )
               );
    if ( iRet < 0 )
    {
        perror( "bind" );
        return( -3 );
    }

    // 接続の許可
    iRet = listen( srcSocket, 1 );
    if ( iRet < 0 )
    {
        perror( "listen" );
        return( -4 );
    }

    // 接続の受付け
    outputLog( "SV""接続を待っています\n" );
    dstSocket = accept( srcSocket
                      , ( struct sockaddr* )&dstAddr
                      , &dstAddrSize
                      );
    outputLog( "SV""accept OK\n" );

    close( srcSocket );

    int iProc = 1;
    while( iProc )
    {
        int iInpt;
        outputLog( "SV""----------------------------------\n" );
        outputLog( "SV""(1) send messase\n" );
        outputLog( "SV""(2) send messase (0byte)\n" );
        outputLog( "SV""(9) end\n" );
        outputLog( "SV""input number: " );
        scanf( "%d", &iInpt );

        switch( iInpt )
        {
        case 1:
            // メッセージ送信
            memset( pcBuf, 0x00, sizeof( pcBuf ) );
            strcpy( pcBuf, "send server!!" );
            iRet = write( dstSocket, pcBuf, strlen( pcBuf ) );
            if ( iRet < 0 )
            {
                perror( "write" );
                return( -5 );
            }
            outputLog( "SV""send OK!!\n" );
            break;
        case 2:
            // メッセージ送信(0byte)
            memset( pcBuf, 0x00, sizeof( pcBuf ) );
            iRet = write( dstSocket, pcBuf, strlen( pcBuf ) );
            if ( iRet < 0 )
            {
                perror( "write" );
                return( -5 );
            }
            outputLog( "SV""send OK!!\n" );
            break;
        case 9:
            outputLog( "SV""終了します。\n" );
            iProc = 0;
            break;
        default:
            outputLog( "SV""番号を選んで下さい。\n" );
            break;
        }
    }

    close( dstSocket );

    outputLog( "SV""LC114Server END\n" );
    return( 0 );
}

メイクファイルです。

makefile
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
# 2013/11/25 (c) ymlib.com
TARGET = LC114Server
OBJS = LC114Server.o outputLog.o
CC = /usr/bin/gcc

$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS)
.SUFFIXES: .c.o
.c.o:
$(CC) -Wall -c $< -g

clean:
rm -f $(TARGET) $(OBJS)

まずはサーバーを起動し、続いてクライアントを起動し両方とも処理番号入力待ちにします。 この状態でクライアントを 1 で受信待ち状態にします。

15:24:23 CL LC113Client START
15:24:23 CL connect OK
15:24:23 CL ----------------------------------
15:24:23 CL (1) recv message(wait)
15:24:23 CL (2) recv message(don't wait)
15:24:23 CL (9) end
15:24:23 CL input number: 1

サーバー側で 2 (0バイトメッセージの送信)をします。

15:24:23 SV input number: 2
15:26:32 SV send OK!!
15:26:32 SV ----------------------------------
15:26:32 SV (1) send messase
15:26:32 SV (2) send messase (0byte)
15:26:32 SV (9) end
15:26:32 SV input number:

正常に送信できたようです。 ですが、クライアント側はメッセージの受信待ちのままでした。 サーバー側で 1 で普通にメッセージを送信したところ、クライアント側で受信しました。 0バイトのメッセージはどこかで無くなっているようです。 元から0バイト=無いも同然なので、送信できないのでしょうか。

複数メッセージ送信

サーバーとクライアントを接続後、サーバーで3回メッセージを送信します。

17:16:30 SV LC114Server START
17:16:30 SV 接続を待っています
17:16:31 SV accept OK
17:16:31 SV ----------------------------------
17:16:31 SV (1) send messase
17:16:31 SV (2) send messase (0byte)
17:16:31 SV (9) end
17:16:31 SV input number: 1
17:16:32 SV send OK!!
17:16:32 SV ----------------------------------
17:16:32 SV (1) send messase
17:16:32 SV (2) send messase (0byte)
17:16:32 SV (9) end
17:16:32 SV input number: 1
17:16:33 SV send OK!!
17:16:33 SV ----------------------------------
17:16:33 SV (1) send messase
17:16:33 SV (2) send messase (0byte)
17:16:33 SV (9) end
17:16:33 SV input number: 1
17:16:33 SV send OK!!
17:16:33 SV ----------------------------------
17:16:33 SV (1) send messase
17:16:33 SV (2) send messase (0byte)
17:16:33 SV (9) end
17:16:33 SV input number:

続いてクライアント側で受信します。 今回は 2 の don't wait で受信してみます。

17:18:00 CL recv=[send server!!send server!!send server!!] len=[39] errno=[0] msg=[Success]
17:18:00 CL ----------------------------------
17:18:00 CL (1) recv message(wait)
17:18:00 CL (2) recv message(don't wait)
17:18:00 CL (9) end
17:18:00 CL input number:

3回分のメッセージをまとめて受信しました。 recv は send の回数分受信するわけではないようです。 この場合、サーバーは3回 send したので、3回メッセージを送ったと思っていますが、 クライアント側は recv 1回なので、長いメッセージを1回だけ受信したと思っています。

「メッセージはまとまって受信する可能性がある」という事を認識してプログラムを書くように注意が必要ですね。

▲ PageTop  ■ Home


Copyright (C) 2013 ymlib.com