TCP 를 통해서 Newwrok Throughput 을 확인하는 툴이다. (UDP도 가능)

영어로 된 옵션들 보기 좋으라고 간단하게 한글로 썼다.

   

   

 클라이어트 모드 -c 옵션 주면 된다

#iperf -c 10.1.1.1

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 16384 Byte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 33453 connected with 10.1.1.1 port 5001

[ 3]   0.0-10.2 sec   1.26 MBytes   1.05 Mbits/sec

   

서버모드   -s 옵션 주면된다.

#iperf -s

------------------------------------------------------------

Server listening on TCP port 5001

TCP window size: 8.00 KByte (default)

------------------------------------------------------------

[852] local 10.1.1.1 port 5001 connected with 10.6.2.5 port 33453

[ ID]   Interval          Transfer       Bandwidth

[852]   0.0-10.6 sec   1.26 MBytes   1.03 Mbits/sec

   

   

클라이언트모드에  -f  옵션 주면

결과 값을 설정 가능하다. 아래와 같이 -f b 로 하면 bits로 나오는데

bits(b), bytes(B), kilobits(k), kilobytes(K), megabits(m), megabytes(M), gigabits(g) or gigabytes(G).

이런식으로 볼 수 있다.

#iperf -c 10.1.1.1 -f b

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 16384 Byte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 54953 connected with 10.1.1.1 port 5001

[ 3]   0.0-10.2 sec   1359872 Bytes   1064272 bits/sec

#iperf -s

------------------------------------------------------------

Server listening on TCP port 5001

TCP window size: 8.00 KByte (default)

------------------------------------------------------------

[852] local 10.1.1.1 port 5001 connected with 10.6.2.5 port 33453

[ ID]   Interval          Transfer       Bandwidth

[852]   0.0-10.6 sec   920 KBytes   711 Kbits/sec

   

윈도우 사이즈옵션 주려면 -w 하고 숫자 넣어주면 간단하게 된다.   

요거는 서버 쪽에서도 맞춰 줘야 한다.

#iperf -c 10.1.1.1 -w 2000

WARNING: TCP window size set to 2000 bytes. A small window size

will give poor performance. See the Iperf documentation.

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 3.91 KByte (WARNING: requested 1.95 KByte)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 51400 connected with 10.1.1.1 port 5001

[ 3]   0.0-10.1 sec   704 KBytes   572 Kbits/sec

   

#iperf -s -w 4000

------------------------------------------------------------

Server listening on TCP port 5001

TCP window size: 3.91 KByte

------------------------------------------------------------

[852] local 10.1.1.1 port 5001 connected with 10.6.2.5 port 51400

[ ID]   Interval          Transfer       Bandwidth

[852]   0.0-10.1 sec   704 KBytes   570 Kbits/sec

 

포트 번호 설정은 -p, 그리고 -t는 전체 시간이고 -i는 인터벌(시간간격)
가지고 구하는 경우

#iperf -c 10.1.1.1 -p 12000 -t 20 -i 2

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 12000

TCP window size: 16.0 KByte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 58316 connected with 10.1.1.1 port 12000

[ 3]    0.0- 2.0 sec    224 KBytes    918 Kbits/sec

[ 3]    2.0- 4.0 sec    368 KBytes    1.51 Mbits/sec

[ 3]    4.0- 6.0 sec    704 KBytes    2.88 Mbits/sec

[ 3]    6.0- 8.0 sec    280 KBytes    1.15 Mbits/sec

[ 3]    8.0-10.0 sec    208 KBytes    852 Kbits/sec

[ 3]   10.0-12.0 sec   344 KBytes    1.41 Mbits/sec

[ 3]   12.0-14.0 sec   208 KBytes    852 Kbits/sec

[ 3]   14.0-16.0 sec   232 KBytes    950 Kbits/sec

[ 3]   16.0-18.0 sec   232 KBytes    950 Kbits/sec

[ 3]   18.0-20.0 sec   264 KBytes    1.08 Mbits/sec

[ 3]    0.0-20.1 sec   3.00 MBytes   1.25 Mbits/sec

 

#iperf -s -p 12000

------------------------------------------------------------

Server listening on TCP port 12000

TCP window size: 8.00 KByte (default)

------------------------------------------------------------

[852] local 10.1.1.1 port 12000 connected with 10.6.2.5 port 58316

[ ID] Interval Transfer Bandwidth

[852]   0.0-20.1 sec   3.00 MBytes   1.25 Mbits/sec

   

 

   

Maximum Segment Size (-m argument) MSS 크기 설정 가능하게 해준다.
디폴트값은 1500Bytes.

  

Client side:

   

   

#iperf -c 10.1.1.1 -m

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 16.0 KByte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 41532 connected with 10.1.1.1 port 5001

[ 3]   0.0-10.2 sec   1.27 MBytes   1.04 Mbits/sec

[ 3] MSS size 1448 bytes (MTU 1500 bytes, ethernet)

   

Here the MSS is not equal to 1500 - 40 but to 1500 - 40 - 12 (Timestamps option) = 1448

   

   

#iperf -c 10.1.1.1 -M 1300 -m

WARNING: attempt to set TCP maximum segment size to 1300, but got 536

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 16.0 KByte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 41533 connected with 10.1.1.1 port 5001

[ 3]   0.0-10.1 sec   4.29 MBytes   3.58 Mbits/sec

[ 3] MSS size 1288 bytes (MTU 1328 bytes, unknown interface)

   

병렬 테스트를 하고자 하면 -p 옵션 주면 된다.

Client side:

   

   

#iperf -c 10.1.1.1 -P 2

------------------------------------------------------------

Client connecting to 10.1.1.1, TCP port 5001

TCP window size: 16.0 KByte (default)

------------------------------------------------------------

[ 3] local 10.6.2.5 port 41534 connected with 10.1.1.1 port 5001

[ 4] local 10.6.2.5 port 41535 connected with 10.1.1.1 port 5001

[ 4]     0.0-10.1 sec   1.35 MBytes   1.12 Mbits/sec

[ 3]     0.0-10.1 sec   1.35 MBytes   1.12 Mbits/sec

[SUM]  0.0-10.1 sec   2.70 MBytes   2.24 Mbits/sec

   

마지막으로 내가 사용하는 주로 쓰는 옵션은..
-n 옵션은  Transfer하는 데이터 크기를 정해서 주고 받는 옵션이다.


클라이언트

$ iperf -c 10.10.1.57 -p 50000 -n 300M
------------------------------------------------------------
Client connecting to 10.10.1.57, TCP port 50000
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  3] local 10.10.4.55 port 41529 connected with 10.10.1.57 port 50000
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-26.3 sec    300 MBytes  95.8 Mbits/sec

 

서버

$ iperf -s -p 50000
------------------------------------------------------------
Server listening on TCP port 50000
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  4] local 10.10.1.57 port 50000 connected with 10.10.4.55 port 41529
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-26.8 sec    300 MBytes  93.7 Mbits/sec
   

   

Client/Server:

   

-f

-i

-l

-m

-p

-u

-w

-B

-C

-M

-N

-V

--format

--interval

--len

--print_mss

--port

--udp

--window

--bind

--compatibility

--mss

--nodelay

--IPv6Version

[kmKM]

#

#[KM]

   

#

   

#[KM]

"host"

   

#

   

   

format to report: Kbits, Mbits, KBytes, MBytes

seconds between periodic bandwidth reports

length of buffer to read or write (default 8 KB)

print TCP maximum segment size (MTU - TCP/IP header)

server port to listen on/connect to

use UDP rather than TCP

TCP window size (socket buffer size)

bind to "host", an interface or multicast address

for use with older versions does not sent extra msgs

set TCP maximum segment size (MTU - 40 bytes)

set TCP no delay, disabling Nagle's Algorithm

Set the domain to IPv6

Server specific:

   

-s

-U

-D

--server

--single_udp

--daemon

               

   

   

run in server mode

run in single threaded UDP mode

run the server as a daemon

Client specific:

   

-b

-c

-d

-n

-r

-t

-F

-I

-L

-P

-T

--bandwidth    

--client

--dualtest

--num

--tradeoff

--time

--fileinput

--stdin

--listenport

--parallel

--ttl

#[KM] 

"host"

   

#[KM]

   

#

"name"

   

#

#

#

for UDP, bandwidth to send at in bits/sec (default 1 Mbit/sec, implies -u)

run in client mode, connecting to "host"

Do a bidirectional test simultaneously

number of bytes to transmit (instead of -t)

Do a bidirectional test individually

time in seconds to transmit for (default 10 secs)

input the data to be transmitted from a file

input the data to be transmitted from stdin

port to recieve bidirectional tests back on

number of parallel client threads to run

time-to-live, for multicast (default 1)

Miscellaneous:

   

-h

-v

--help

--version

                    

   

print this message and quit

print version information and quit

 

반응형

간단하게 리소스 카운터라고 생각해도 되는데 일단은 데드락 피하기 위한

기술 중의 하나라고 한다..

실제 어디다 써먹을지는 아직 모르겠지만.. 이거보다는 개인적으로 뮤텍스를 더 자주 쓰는듯 싶네..

 

소스코드 출처 : http://forum.falinux.com/zbxe/?document_srl=428639

 

int semget ( key_t key, int nsems, int semflg )

세마포어 식별자를 가지고 오는 함수다.

 

key_t key

시스템에서 세머포어를 식별하는 키 번호

int nsems

세마포어 집합 내의 세마포어 개수로 접급 제한하려는 세마포어 자원의 개수

int semflg 동작 옵션 ( IPC_CREATE와 IPC_EXCL이 있다.)

 

 

int semctl ( int semid, int semnum, int cmd, union semun arg)

세마포어를 control 하는 함수다.

 

int semid 시스템에서 세머포어를 식별하는 집합 번호
int semnum

세마포어 집합 내에서의 세마포어 위치 (세마포어 넘버...)

int cmd

제어 명령( 값을 설정, 삭제, 소유권, 등등 많다.)

union semun arg 위의 제어명령 cmd 에 따라 달라진다., 설정 또는 값을 구하는 변수 
union semun{
   int                  val;
   struct   semid_ds   *buf;
   unsigned short int  *arrary;
}

int semop ( int semid, struct sembuf *sops, unsigned nsops )

세마포어의 값을 변경한다. 값을 증가, 감소시킨다.

 

int semid 시스템에서 세머포어를 식별하는 집합 번호
struct sembuf *sops

세마포어 값을 계산하기위한 설정 값 
struct sembuf {
    short sem_num;   세마포어 번호
    short sem_op;     세마포어 증감값
    short sem_flg;     옵션 
}

unsigned nsops

변경하려는 세마포어 개수로 변경하려는 세마포어 개수가 여러 개일 때 사용
n개의 세마포어 옵션들..

 

 

예제를 봐야 이게 뭔지 조금은 이해가 간다.

매우간단한 멀티 쓰레드 구조의 카운터다.

failinux.com.. 참 괜찮다.

 

 

============================================

#include 
#include 
#include 
#include 
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/poll.h"

int         cnt   = 0;
static int  semid;

void semop1() 
{
    struct sembuf buf1;

    buf1.sem_num   = 0;
    buf1.sem_op    = -1;
    buf1.sem_flg   = SEM_UNDO;

    if (semop(semid, &buf1, 1) == -1)
        printf( "%s::semop() Fail\n", __func__);
}

void semop2()
{
    struct sembuf buf2;

    buf2.sem_num   = 0;
    buf2.sem_op    = 1;
    buf2.sem_flg   = SEM_UNDO;

    if (semop(semid, &buf2, 1) == -1)
        printf( "%s::semop() Fail\n", __func__);
}

void *fun_thread1(void *arg) {
    while( 1) {
        semop1();
        printf( "thread1 run \n");
        if ( 5 < cnt) {
            printf( "thread1 Completely terminated \n");
            semop2();
            break;
        }
        else {
            cnt++;
            poll(0,0,100);
            printf( "thread1 terminated \n");
        }
        semop2();
    }
    return;
}

void *fun_thread2(void *arg)
{
    while( 1) {
        semop1();
        printf( "thread2 run \n");
        if (5 < cnt) {
            printf( "thread2 Completely terminated \n");
            semop2();
            break;
        }
        else {
            printf( "=====>>Counter= %d\n", cnt);
            poll(0,0,100);
            printf( "thread1 terminated \n");
        }
        semop2();
    }

    return;
}

int main(int argc, char *argv[])
{
    pthread_t thread1;
    pthread_t thread2;
    union semun{
        int                  val;
        struct   semid_ds   *buf;
        unsigned short int  *arrary;
    }arg;

    if ((semid = semget( IPC_PRIVATE, 1, IPC_CREAT| 0666)) == -1) {
        printf( "semget() Fail\n");
        return -1;
    }

    arg.val=1;                // Semaphore value = 1
    if (semctl(semid, 0, SETVAL, arg) == -1) {
        printf( "semctl()-SETVAL Fail\n");
        return -1;
    }

    pthread_create(&thread1, NULL, fun_thread1, NULL);
    pthread_create(&thread2, NULL, fun_thread2, NULL);
    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);

    if (semctl(semid, 0, IPC_RMID, arg) == -1) {
        printf( "semctl()-IPC_RMID Fail\n");
        return -1;
    }
    printf( "Process Terminated!");
    return 0;
}
/* The end of function */
# 수행결과는 다음과 같다.
./a.out
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 1
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 2
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 3
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 4
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 5
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
thread2 Completely terminated 
thread1 run 
thread1 Completely terminated 

 

 

============================================

 

failinux 그대로 가져왔슴..

개인적인 테스트용이므로,, 저작권에 문제가 있다면

알려주시길.. 지우던지 다른 방식으로 구현해두겠습니다.

반응형

'Language > C' 카테고리의 다른 글

select 함수 예제  (8) 2012.07.23
Unix Domain Socket 예제  (6) 2012.07.23
mmap / munmap 함수 예제  (10) 2012.07.17
shmget/ shmat 함수 예제  (6) 2012.07.13
C FAQ (포인터 증가 3)  (6) 2012.07.13
파일이나 디바이스를 주소 공간 메모리에 대응시키는 방식인데

일종의 IPC 통신으로 사용가능하다. 매우 빠름.

 

출처 : 소스코드 http://www.cs.purdue.edu/homes/fahmy/cs503/mmap.txt

 

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

파일이나 디바이스를 응용 프로그램의 주소 공간 메모리에 대응시킨다.

 

1인자 => 시작 포인터 주소 (아래의 예제 참조)

2인자 => 파일이나 주소공간의 메모리 크기

3인자 => PROT 설정 (읽기, 쓰기, 접근권한, 실행)

4인자 => flags는 다른 프로세스와 공유할지 안할지를 결정한다.

5인자 => fd는 쓰거나 읽기용으로 열린 fd값을 넣어준다.

6인자 => offset은 0으로 하던지 알아서 조절한다.

 

int munmap(void* start, size_t length);

할당된 메모리 영역을 해제한다.

 

1인자 => 위에 mmap으로 지정된 포인터값 넣어주고

2인자 => 위에서 사용했던 length와 동일하게 넣어준다.

(왜냐면.. 할당했던거 동일하게 해제해야 하니깐..)

 

더 자세한 사항은 man page에 모든게 나와있음.

 

==============================================================

#include 
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/mman.h" /* mmap() is defined in this header */

int main (int argc, char *argv[])
{
    int fdin, fdout;
    char *src, *dst;
    struct stat statbuf;

    if (argc != 3) {
        printf("usage: a.out  \n");
        return -1;
    }

    /* open the input file */
    if ((fdin = open (argv[1], O_RDONLY)) < 0) {
        printf ("can't open %s for reading", argv[1]);
        return -2;
    }
    /* open/create the output file */
    if ((fdout = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) {
        printf ("can't create %s for writing", argv[2]);
        return -2;
    }

    /* find size of input file */
    if (fstat (fdin,&statbuf) < 0) {
        printf ("fstat error");
        return -2;
    }

    /* go to the location corresponding to the last byte */
    if (lseek (fdout, statbuf.st_size - 1, SEEK_SET) == -1) {
        printf ("lseek error");
        return -2;
    }

    /* write a dummy byte at the last location */
    if (write (fdout, "", 1) != 1) {
        printf ("write error");
        return -2;
    }
    /* mmap the input file */
    if ((src = mmap(0, statbuf.st_size, PROT_READ,
                    MAP_SHARED, fdin, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for input");
        return -2;
    }

    /* mmap the output file */
    if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE,
                    MAP_SHARED, fdout, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for output");
        return -2;
    }

    /* this copies the input file to the output file */
    memcpy (dst, src, statbuf.st_size);

    munmap(src, statbuf.st_size);
    munmap(dst, statbuf.st_size);

    return 0;
} /* main */
/* The end of function */
실행 후 결과 화면 
$ ./a.out test test_out
$ ls -al
drwxr-xr-x  2 jeon jeon 4096 Jul 17 08:39 .
drwx------ 12 jeon jeon 4096 Jul 17 08:39 ..
-rwxr-xr-x  1 jeon jeon 6410 Jul 17 08:39 a.out
-rw-r--r--  1 jeon jeon 1844 Jul 17 08:39 mmap.c
-rw-r--r--  1 jeon jeon  469 Jul 17 08:29 test
-rw-------  1 jeon jeon  469 Jul 17 08:39 test_out

 

==============================================================

 

test라는 입력파일은 미리 생성하고

test_out은 위의 프로그램을 실행하고 생성된 파일이다.

생각보다 간단한것 같은데.

최대 어느정도까지 매핑시키는지는 추후에 해봐야겠다..

반응형

'Language > C' 카테고리의 다른 글

Unix Domain Socket 예제  (6) 2012.07.23
semget. semop, semctl 함수 예제  (12) 2012.07.17
shmget/ shmat 함수 예제  (6) 2012.07.13
C FAQ (포인터 증가 3)  (6) 2012.07.13
nmemb 의미  (8) 2012.07.12

IPC 통신의 그다음 핵심인 Shared Memory 이용이다.

 

출처 : http://www.cs.cf.ac.uk/Dave/C/node27.html ,  http://failinux.com

 

int shmget(key_t key, int size, int shmflg);

 

key_t key 공유 메모리를 구별하는 식별 번호
int size 공유 메모리 크기
int shmflg 동작 옵션

 

 

void *shmat(int shmid, const void *shmaddr, int shmflg);

 

int shmid 공유 메모리를 구별하는 식별 번호
void *shmaddr 첨부되는 어드레스 주소. 일반적으로 NULL을 지정
int shmflg

동작 옵션

key값만 서로 맞추면 제대로 동작한다.

예제코드는 shm_server와 shm_client이고

서버쪽은 메모리에 쓰는역할

클라이언트쪽은 메모리에서 읽는 역할을 한다.

=============================================================

==== shm_server.c ====
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/shm.h"
#include 

#define SHMSZ     27

int main()
{
    char c;
    int shmid;
    key_t key;
    char *shm, *s;

    /* We'll name our shared memory segment
     * "5678".  */
    key = 9678;

    /* Create the segment.  */
    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        return -1;
    }

    /* Now we attach the segment to our data space.  */
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        return -1;
    }

    /* Now put some things into the memory for the
     * other process to read.  */
    s = shm;

    for (c = 'a'; c <= 'z'; c++)
        *s++ = c;
    *s = NULL;

    /*
     * Finally, we wait until the other process 
     * changes the first character of our memory
     * to '*', indicating that it has read what 
     * we put there.
     */
    while (*shm != '*')
        sleep(1);

    return 0;
}
==== shm_client.c ====
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/shm.h"
#include 

#define SHMSZ     27

int main()
{
    int shmid;
    key_t key;
    char *shm, *s;

    /* We need to get the segment named
     * "5678", created by the server.  */
    key = 5678;

    /* Locate the segment.  */
    if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
        perror("shmget");
        return -1;
    }

    /* Now we attach the segment to our data space.  */
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        return -1;
    }

    /* Now read what the server put in the memory.  */
    for (s = shm; *s != NULL; s++)
        putchar(*s);
    putchar('\n');

    /*
     * Finally, change the first character of the 
     * segment to '*', indicating we have read 
     * the segment.
     */
    *shm = '*';

    return 0;
}
== 서버측은 결과가 나오지않는다. ==
== 클라이언트측 결과는 다음과 같다. ==
$ ./clie 
abcdefghijklmnopqrstuvwxyz

 

=============================================================

 

위의 프로그램은 a-z까지 출력하는건데

키값은 5678이다. 이걸 16진수로 변환하면 162e가 되는데 이건

%ipcs 명령으로 확인하면 생성된것을 볼 수 있다.

---- 중략 ----

0x0000162e 4292650    test      666        27         2

---- 후략 ----

 

위에서 define으로 결정한 크기를 넘어서게 되면 앞쪽은 잘리고

뒤에만 출력되게 된다.

반응형

'Language > C' 카테고리의 다른 글

semget. semop, semctl 함수 예제  (12) 2012.07.17
mmap / munmap 함수 예제  (10) 2012.07.17
C FAQ (포인터 증가 3)  (6) 2012.07.13
nmemb 의미  (8) 2012.07.12
msgsnd/ msgrcv 함수 예제  (12) 2012.07.12

출처 : www.cfaq.com

Q: I have a char * pointer that happens to point to some ints, and I want to step it over them. Why doesn't

((int *)p)++;

work?

int 형 포인터인데 왜 저렇게는 증가가 안되는건가?   

A: In C, a cast operator does not mean ``pretend these bits have a different type, and treat them accordingly''; it is a conversion operator, and by definition it yields an rvalue, which cannot be assigned to, or incremented with ++. (It is either an accident or a deliberate but nonstandard extension if a particular compiler accepts expressions such as the above.) Say what you mean: use

        p = (char *)((int *)p + 1);

or (since p is a char *) simply

        p += sizeof(int);

or (to be really explicit)

        int *ip = (int *)p;
        p = (char *)(ip + 1);

When possible, however, you should choose appropriate pointer types in the first place, rather than trying to treat one type as another.

See also question 16.7.

References: K&R2 Sec. A7.5 p. 205

ISO Sec. 6.3.4

Rationale Sec. 3.3.2.4

H&S Sec. 7.1 pp. 179-80

반응형

'Language > C' 카테고리의 다른 글

mmap / munmap 함수 예제  (10) 2012.07.17
shmget/ shmat 함수 예제  (6) 2012.07.13
nmemb 의미  (8) 2012.07.12
msgsnd/ msgrcv 함수 예제  (12) 2012.07.12
C FAQ (포인터 증가 2)  (6) 2012.07.12

기본적인 이론에 대한 글이라 저작권이라기에도 참 애매하다..

출처 : http://www.otl.ne.kr/

TCP 연결 단계 (RFC 793)

       TCPA                                                                                         TCP B

1.  CLOSED                                                                                            LISTEN

2.  SYN-SENT    --> < SEQ=100>< CTL=SYN>                                   -->  SYN-RECEIVED

3.  ESTABLISHED <-- < SEQ=300>< ACK=101>< CTL=SYN,ACK>       <--    SYN-RECEIVED

4.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>                -->  ESTABLISHED

5.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>< DATA>   -->  ESTABLISHED

 

LISTEN       : 데몬이 요청을 발을 수 있도록 연결 요구를 기다리는 상태.

                   , http(80), mail(25), ftp(21), telnet(23) 등의 포트가 열려있음을 의미.

                   윈도우즈에서는 LISTENING으로 표시.

SYN_SENT : 로컬에서 원격으로 연결 요청(SYN 신호를 보냄)을 시도한 상태.

SYN_RECV : 원격으로 부터 연결 요청을 받은 상태.

                   요청을 받아 SYN+ACK 신호로 응답은 한 상태이지만 ACK는 받지 못했다.

                   netstat로 확인할 때 SYN_RECV가 아주 많다면 TCP SYN 플러딩(Flooding) 공격일 가능성이 있다.

                   윈도우즈와 솔라리스에서는 SYN_RECEIVED으로, FreeBSD SYN_RCVD으로 표시.

ESTABLISHED : 서로 연결이 되어 있는 상태

                   위에서 192.168.123.10의 포트 32794 218.xxx.xx.xx의 포트 22(ssh)이 서로 연결되어 있는 상태.

 

  

TCP 종료 단계

* 정상적인 연결 종료 과정

      TCP A                                                                                     TCP B

1.  ESTABLISHED                                                                           ESTABLISHED

2.  (Close)

     FIN-WAIT-1       --> <SEQ=100><ACK=300><CTL=FIN,ACK>  -->  CLOSE-WAIT

3.  FIN-WAIT-2      <--  <SEQ=300><ACK=101><CTL=ACK>       <--   CLOSE-WAIT

4.                                                                                                 (Close)

    TIME-WAIT      <--  <SEQ=300><ACK=101><CTL=FIN,ACK>  <--    LAST-ACK

5.  IME-WAIT         --> <SEQ=101><ACK=301><CTL=ACK>         -->  CLOSED

6.  (2 MSL)

     CLOSED                                                    

 

FIN_WAIT1     : 소켓이 닫히고 연결이 종료되고 있는 상태. 원격의 응답은 받을 수 있다.

                      솔라리스에서는 FIN_WAIT_1로 표시.

FIN_WAIT2     : 로컬이 원격으로 부터 연결 종료 요구를 기다리는 상태.

                      솔라리스에서는 FIN_WAIT_2로 표시.

CLOSE_WAIT : 원격의 연결 요청을 받고 연결이 종료되기를 기다리는 상태 .

                      원격으로 부터 FIN+ACK 신호를 받고 ACK 신호를 원격에 보냈다.

TIME_WAIT    : 연결은 종료되었으나 원격의 수신 보장을 위해 기다리고 있는 상태.

                      이 상태를 특히 자주 보게되는 경우 => Apache에서 KeepAlive OFF로 해둔 경우, Tomcat 서버를 쓰는 경우 등.

LAST_ACK    : 연결은 종료되었고 승인을 기다리는 상태.

CLOSED       : 완전히 연결이 종료된 상태.

 

※ 위의 FIN_WAIT1, FIN_WAIT2, CLOSE_WAIT 3개 상태는

    연결 종료를 위해 서로간에 신호를 주고받는 과정에 나타나는 상태로 이해하면 된다.

    종료 요청을 한 곳에서는 FIN_WAIT1, FIN_WAIT2, TIME_WAIT 상태가,

    종료 요청을 받는 곳에서는 CLOSE_WAIT, LAST_ACK 상태가 표시된다.

 

 

 

 

 

TIME_WAIT 상태 없애기

이미 발생한 TIME_WAIT 상태는 일정시간이 지나면 없어지지만,

client server에 매우 빈번히 connect/disconnect를 반복한다면

많은 TCP portTIME_WAIT 상태가 되서 문제가 생길 수 있음.

 

client application에서 socket option linger option off 시키면,

client에 의한 connection close TIME_WAIT 상태를 거치지 않고

ClOSED 상태로 바뀌게 되므로, TIME_WAIT 상태가 발생하지 않게 됨.

 

/* 중략 */

int sock

struct linger   ling;

 

ling.l_onoff = 1;

ling.l_linger = 0;      /* 0 for abortive disconnect */

 

setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling))

 

 

 

 

 

 

TCP 상태별 정의

ESTABLISHED

   3단계 핸드쉐이킹 후 연결 성립

 

SYN_SENT

   원격 호스트에 능동적인 개설 요청(능동적 열기)

 

SYN_RECV

   네트워크 통한 연결요청 받음(수동적 열기)

 

FIN_WAIT1

   능동적 닫기(active close) 요청을 한 상태

 

FIN_WAIT2

   로컬에서 종결(FIN)세그먼트를 전송하였고 원격 시스템에서 이에 대한 확인메시지를 수신하였지만,

   원격 애플리케이션이 작업을 종료하지 않아 원격 호스트의 종결 세그먼트를 기다리는 상태

 

TIME_WAIT

   회선의 종결 절차가 완료되었지만 분실되었을지 모르는 느린 세그먼트를 위해

   소켓을 열어 놓고 유지하고 있는 상태

 

CLOSED

   회선이 종결되고 모든 자원을 해제한 상태

 

CLOSE_WAIT

   수동적 닫기를 하고 있는 상태로 FIN 종결 세그먼트를 수신하고 이에 대한 확인 메시지를 전송한 상태

 

LAST_ACK

   FIN 종결 요청을 받고 로컬에서도 회선 종결에 합의하여 종결을 요청(FIN)한 상태로

   이에 대한 확인 메시지가 수신되면 회선이 종결됨

 

LISTEN

   서버 애플리케이션에서 수동적 열기로 연결 요청을 기다리고 있는 상태

 

CLOSING

   로컬 TCP FIN_WAIT_1에서 설명한대로 FIN 종결 세그먼트를 전송하였고,

   LAST_ACK에서 설명한대로 원격 시스템의 종결 세그먼트도 수신하였지만,

   FIN_WAIT_1 단계에서 전송한 세그먼트에 대한 확인 메시지(ACK)를 수신하지 못한 상태로

   보통 확인 메시지가 전송 도중 분실되었다는 것을 나타냄

 

UNKOWN

   소켓의 상태에 대해서 확인이 안되는 경우

 

 

반응형

fread, fwitte, calloc 등에서 나온다.

calloc의 man page를 보다보면 아래와 같이 나온다.

  void *calloc(size_t nmemb, size_t size);

nmemb 는 number of members이고 간단하게

count정도로 여기면 된다.

더 간단히.. 개수..


반응형

'Language > C' 카테고리의 다른 글

shmget/ shmat 함수 예제  (6) 2012.07.13
C FAQ (포인터 증가 3)  (6) 2012.07.13
msgsnd/ msgrcv 함수 예제  (12) 2012.07.12
C FAQ (포인터 증가 2)  (6) 2012.07.12
C FAQ (포인터 증가에 대해서)  (6) 2012.07.12

출처.: http://www.falinux.com/


IPC의 시작인 메시지큐 통신이다.

 

       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

 

int msqid

메시지 큐  식별자 , msgget 함수의 리턴값이다.

void *msgp

전송할 자료, void 포인터니까 아무 자료형이나 덮어쓰면된다.

size_t msgsz

전송할 자료의 크기, 자료가 구조체건 뭐건 sizeof로 정확한 크기면 된다.

int msgflg

동작 옵션, 큐에 공간이 있을떄까지 기다리면 0, 여유공간 없으면 복귀 시킬경우, IPC_NOWAIT.

 

 

       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

 

int msqid

메시지 큐 식별자, msgget 함수의 리턴값.

void *msgp

전송할 자료, 마찬가지로 아무 자료형이나 선언하기 나름.

size_t msgsz

전송할 자료의 크기, 위에 선언한거에 그냥 sizeof로 정확한 사이즈로 기재하면되고

logn msgtyp

int msgflg

수신할 메시지 타입, 0이면 다 받고 0보다 크면 큐에 가장 처음 메시지에서 타입이 같은거만 받고

동작 옵션

--------------------------------------------------------------------------

=== 메시지 수신하는 코드 ===
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/msg.h"

#define  BUFF_SIZE   1024
#define  KEY   35002

typedef struct {
    int   msgid;
    long  type;
    char  buff[BUFF_SIZE];
} t_data;

int main()
{
    int      msqid;
    t_data   data;

    printf("t_data size = %d\n", sizeof(t_data));
    printf("long size = %d\n", sizeof(long));

    if (( msqid = msgget( (key_t)KEY, IPC_CREAT|0666)) == -1) {
        perror( "msgget() fail");
        return -1;
    }

    while(1)
    {
        /* IPC message recv */
        if(msgrcv(msqid, &data, sizeof(t_data)-sizeof(long), 1, 0) == -1)
        {
            perror( "msgrcv() fail");
            return -2;
        }
        printf( "ID=[%d] MSG => %s\n", data.msgid, data.buff);
    }

    return 0;
}
/* end of the program */
===수신측 결과=== 
ID=[1] MSG => msg_type=0,index=1, message queue program
ID=[1] MSG => msg_type=10,index=11, message queue program
=== 메시지 송신하는 코드 ===
#include 
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/msg.h"
#include 

#define  BUFF_SIZE   1024
#define  KEY         35002

typedef struct {
    int   msgid;
    long  type;
    char  buff[BUFF_SIZE];
} t_data;

int main()
{
    int      msqid;
    int      index   = 0;
    int      ret   = 0;
    t_data   data;

    printf("t_data size = %d\n", sizeof(t_data));
    printf("long size = %d\n", sizeof(long));

    if((msqid = msgget((key_t)KEY, IPC_CREAT|0666))== -1) {
        perror( "msgget() Fail");
        return -1;
    }

    while(1)
    {
        data.type  = index;
        data.msgid =  ((index++ %10)+1);

        sprintf( data.buff, "msg_type=%ld,index=%d, message queue program",
                data.type, index);

        printf( "ID=[%d]  MSG => %s\n", data.msgid, data.buff);

        /* IPC message send */
        ret = msgsnd(msqid, &data, (sizeof(t_data)-sizeof(long)), 0);
        if(ret == -1)
        {
            perror( "msgsnd() Fail");
            return -2;
        }
        /* sleep 2 seconde */
        poll(0, 0, 2000);
    }
    return 0;
}
===송신측 결과 ===
ID=[1]  MSG => msg_type=0,index=1, message queue program
ID=[2]  MSG => msg_type=1,index=2, message queue program
ID=[3]  MSG => msg_type=2,index=3, message queue program
ID=[4]  MSG => msg_type=3,index=4, message queue program
ID=[5]  MSG => msg_type=4,index=5, message queue program
ID=[6]  MSG => msg_type=5,index=6, message queue program
ID=[7]  MSG => msg_type=6,index=7, message queue program
ID=[8]  MSG => msg_type=7,index=8, message queue program
ID=[9]  MSG => msg_type=8,index=9, message queue program
ID=[10]  MSG => msg_type=9,index=10, message queue program
ID=[1]  MSG => msg_type=10,index=11, message queue program
ID=[2]  MSG => msg_type=11,index=12, message queue program

 

--------------------------------------------------------------------------

위에 보면 10으로 나눈 나머지에서 1이 되는 경우에만 수신하도록 구현되어 있다.

 

가장 중요한 부분은

메시지 사이즈 부분에 sizeof(long)만큼을 뺴주었는데

그 이유는 아래와 같다...

전에 이거 몰라서 찾는데 일주일 날린것만 생각하면.. 치가 떨린다...

 

struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};

The mtext field is an array (or other structure) whose size is specified by msgsz, a nonnegative integer value.


반응형

'Language > C' 카테고리의 다른 글

C FAQ (포인터 증가 3)  (6) 2012.07.13
nmemb 의미  (8) 2012.07.12
C FAQ (포인터 증가 2)  (6) 2012.07.12
C FAQ (포인터 증가에 대해서)  (6) 2012.07.12
C-FAQ 어찌되었건 pointer 쓰면 정말 좋은가?  (6) 2012.07.12

+ Recent posts