'Programming/Network Programming'에 해당되는 글 8건

  1. 2011.10.28 TCP packet and ICMP packet analysis
  2. 2011.10.28 TCP programming basis
  3. 2011.10.26 .. no regret..
  4. 2011.10.15 The example of one server that sends a client ID
  5. 2011.10.10 get client IPadrress in server side
  6. 2011.09.29 Reference for unix socket api
  7. 2011.09.21 TCP/IP
  8. 2011.09.07 The concept of TCP/IP part 1. 2


1. 서버에 연결하기 위해 전송 되는 SYN 패킷

 

 


패킷분석 (순서는 Segment -> Datagram -> Frame)
패킷은 www.dankook.ac.kr 대학으로 접속하는 경로이며, 주소의 IP 203.237.226.85이다.

1)      TCP header(20bytes + 12bytes as option)

a)      Source port : 1718 // 응용프로그램의 포트번호

b)      Destination port : http(80) // 예약된 http 포트넘버를 쓴다, 최초 http서버로 접속

c)       Sequence number : 0     // relative value이며 실제로는 client에서 생성한 랜덤한 값이 들어간다.

d)      Acknowledge number : 0             // 최초 SYN 패킷을 보낼 때는 항상 0으로 초기화 된다.

e)      Header length : 32 bytes               // 20 bytes(Original header) + Option(

f)       Flag : 0x02                                           // SYN flag Set 되어있는 상황이다.

g)      Window size : 8192                          // Window size 현재 recv buffer 비어있는 크기를 말한다.

h)      Check sum                                          // CRC 이용하여 checksum 수행한다(4byte)

i)        Urgent point : 0                                // 긴급한 data 아니므로, 부분은 비어져 있다.

j)        Option (12bytes)

i)        Maximum segment size(MSS) : 1460               // TCP 옵션 부분이며, TCP 혹은 IP헤더로 count되지 않는다.
(4bytes)                                                       // Header + MSS <= MTU 여야 하며, 값은 하나의 segment 가지는 최대 크기이다.
                                                                        // MTU 1500으로 설정되어 있으므로 1500 – 20(IP header) + 20(TCP header) = 146

ii)       Window scale(3bytes) : 2                     // receive buffer(Window size) 증가시키기 위한 옵션으로 power(2, ws) 표현된다.
                                                                        // 경우 buffer 8192 * power(2,2) 므로 32768 byte 확장되게 된다.

iii)     SACK_PERM(2bytes) : 1                                        // ,수신시 다양한 패킷의 손실을 예방하기 위해서 만들어 졌으며,
 (RFC 2018기준)                                      // 수신자는 송신자에게 모든 segment 성공적으로 도착했음을 알리는 역할을 한다.

 


 

 

2)      IPv4 Header(20bytes)

a)      Version  : 4                                          // IPv4 나타낸다

b)      Header length : 20                           // 헤더의 크기를 나타낸다

c)       Service : 0x00                                     // Default service 나타낸다

d)      Total length : 52                                // Datagram 크기를 나타낸다, TCP encapsulated 되었다.

e)      Identification : 0x2853                    // datagram ID 나타낸다

f)       Flags : 0x02                                         // Don’t fragment, 데이터를 나누지 않는다.

g)      Fragment offset : 0                         // SYN packet Fragment offset 가질 필요가 없다.

h)      Time to live = 128                             // 보통 256으로 초기화 되며, Hop 지날때마다 한개씩 감소하게 된다.

i)        TYPE  = TCP(6)                                   // TCP 캡슐화 IP 헤더이다

j)        Checksum                                           // 2바이트의 Checksum, 오류 체크를 한다.

k)      Source IP addr : 192.168.0.3         // 송신자의 IP주소를 나타낸다(공유기를 썻기 때문에 가상 IP주소가 나타났다.)

l)        Dest IP addr : 203.237.226.85      // 목적지 IP주소를 나타낸다 www.dankook.ac.kr 서버의 IP주소이다.

 

3)      Ethernet header(14bytes)

a)      Destination(6bytes)                        // 수신자 MAC(Media access control) 주소를 나타낸다.

b)      Source(6bytes)                                 // 송신자 MAC 주소를 나타낸다

c)       TYPE : IP(2bytes)                              // IP Protocol 캡슐화한 Ehternet frame이다.

패킷의 크기는 20(TCP header) + 12(TCP option) + 20(IP header) + 14(Ethernet header)  = 66 bytes
wireShark
표시되는 byte이며WireShark Ethernet Presemble(8byte) CRC(4bytes) 나타내지 않기 때문에
실제 크기는 66 + 12 = 78bytes 된다.


 

 

2. 1024바이트의 데이터를 전송하는 TCP 패킷

 

직접 프로그램을 만들어서 프로그램이 1024 바이트를 전송하도록 하였다.

 

1)      TCP header(20bytes + 12bytes as option)

a)      Source port : 4821                            //  송신자 응용프로그램의 포트번호

b)      Destination port : 7500                 // 만든 프로그램의 port번호가 7500이였다.

c)       Sequence number : 1                     // three way hand-shaking 바로 직후에는 sequence number relative 값으로1이다.

d)      Acknowledge number : 1             // relative acknowledge 역시 1이다(단순히 1024 전송했기 때문에 다음에 값은 없다)

e)      Header length : 22 bytes               // 20 bytes(Original header size)

f)       Flag : 0x18                                           // PSH(버퍼가 비어져 있어도 즉시 전송) + ACK set되어 있다.

g)      Window size : 4380                          // Window size 현재 recv buffer 비어있는 크기를 말한다.

h)      Check sum                                          // CRC 이용하여 checksum 수행한다(4byte)

i)        Urgent point : 0                                                // 긴급한 data 아니므로, 부분은 비어져 있다.

j)        Data 영역은 1024byte 채워져 있다.

2)      IPv4 Header(20bytes)

a)      Version  : 4                                          // IPv4 나타낸다

b)      Header length : 20                           // 헤더의 크기를 나타낸다

c)       Service : 0x00                                     // Default service 나타낸다

d)      Total length : 1064                           // 1024(Data) + 20(IP) + 20(TCP)

e)      Identification : 0x0985                    // datagram ID 나타낸다

f)       Flags : 0x02                                         // Don’t fragment, 데이터를 나누지 않는다.

g)      Fragment offset : 0                         // SYN packet Fragment offset 가질 필요가 없다.


 

 

h)      Time to live = 128                             // 보통 256으로 초기화 되며, Hop 지날때마다 한개씩 감소하게 된다.

i)        TYPE  = TCP(6)                                   // TCP 캡슐화 IP 헤더이다

j)        Checksum                                           // 2바이트의 Checksum, 오류 체크를 한다.

k)      Source IP addr : 192.168.0.3         // 송신자의 IP주소를 나타낸다(공유기를 썻기 때문에 가상 IP주소가 나타났다.)

l)        Dest IP addr : 14.47.140.40           // 목적지 IP주소를 나타낸다, 본인 친구의 컴퓨터와 통신하였다.

 

3)      Ethernet header(14bytes)

a)      Destination(6bytes)                        // 수신자 MAC(Media access control) 주소를 나타낸다.

b)      Source(6bytes)                                 // 송신자 MAC 주소를 나타낸다

c)       TYPE : IP(2bytes)                              // IP Protocol 캡슐화한 Ehternet frame이다.

 

데이터 크기는
                1024byte(data) + 20byte(TCP header) + 20byte(IP header) + 14(Ethernet header) + 8(preamble) + 4(CRC) = 1090 byte
된다

 

 

 

 


 

 

3. 시간초과 오류를 나타내는 ICMP 패킷

 

 


 

Window 환경 내에서TraceRt 이용하여서 Time-excceded ICMP 패킷을 만들었다.

 

1)      ICMP(4byte + 36bytes(Data))

a)      Type : 11                                              // Type 11 Time-exceeded 나타낸다

b)      Code : 0                                                // Type ==11 && Code == 0 TTL expired in transit 의미한다.(전송 시간 초과)

c)       CheckSum(4bytes)                          // 데이터 오류를 체크

d)      Data part tracert 수행했을 IPv4 헤더 + ICMP 헤더로 채워져 있다.

i)        IPv4 header(20bytes)

(1)    Version : 4                                           // IPv4 의미한다.

(2)    Header Length : 20                          // ICMP Data 캡슐화되어있는 IP 헤더 크기

(3)    Service : 0x00                                     // 기본 서비스

(4)    Total length : 92                                // 크기를 나타낸다( 92 되는지는 확실히 모르겠다)

(5)    ID                                                            // IP 식별자

(6)    Flags : 0x00                                         // 0 예약된 bit이다.

(7)    Frag offset : 0                                    // Fragment offset 나타낸다

(8)    Time to live : 1                                   //  Time to live 1에서 0 되는 순간 Router ICMP 다시 보내게 된다.

(9)    Protocol : ICMP                                 // ICMP 캡슐화하고 있던 IP이다.

(10) CheckSum                                          // 오류검출 기능

(11) Source : 192.168.0.3                       // 송신자 IP 주소

(12) Dest      : 203.238.226.85                // 수신하 IP 주소

ii)        ICMP header (8bytes)

(1)    TYPE : 8                                                 // Tracert 썻기 때문에 Echo request 이용하였다.

(2)    Code : 0                                                // Echo request 의미한다(Type 같이 쓰임)

(3)    CheckSum                                           // 오류 검출기능

(4)    The rest of ICMP(4bytes) Identifier Sequence number 정보로 이뤄져 있다

(a)    Identifier(BE)                             // BE Big-endian 의미한다.

(b)   Identifier(LE)                             // LE Little-endian 의미한다.

(c)    Sequence number(BE)          // Sequence number Big-Endian으로 나타냄

(d)   Sequence number (LE)          // Sequence number Little-Endian으로 나타냄

2)      IPv4

a)      Version  : 4                                          // IPv4 나타낸다

b)      Header length : 20                           // 헤더의 크기를 나타낸다

c)       Service : 0x00                                     // Default service 나타낸다

d)      Total length : 56                                // Datagram 크기를 나타낸다, ICMP encapsulated 되었다.

e)      Identification : 0x6a59                    // datagram ID 나타낸다

f)       Flags : 0x00                                         // 예약되어 잇다.

g)      Fragment offset : 0                         // SYN packet Fragment offset 가질 필요가 없다.

h)      Time to live = 248                             // 보통 256으로 초기화 되며, Hop 지날때마다 한개씩 감소하게 된다.

i)        TYPE  = ICMP(1)                                                // ICMP 캡슐화 IP 헤더이다

j)        Checksum                                           // 2바이트의 Checksum, 오류 체크를 한다.

k)      Source IP addr : 203.237.226.85  // IP data router로부터 데이터이다.

l)        Dest IP addr : 192.168.0.3             // 자신의 주소가 된다.

3)      Ethernet(14 bytes)

a)      Destination(6bytes)                        // 수신자 MAC(Media access control) 주소를 나타낸다.

b)      Source(6bytes)                                 // 송신자 MAC 주소를 나타낸다

c)       TYPE : IP(2bytes)                              // IP Protocol 캡슐화한 Ehternet frame이다.

따라서 크기는 4byte(ICMP 헤더) + 36byte(ICMP Data part) + 20byte(IP header) + 14byte(Ethernet header)
                                + 8byte(Preamble) + 4byte(CRC) = 82byte
된다.

 

4. Echo request ICMP 패킷

 


Command Prompt에서 ping 명령을 수행하였으며 대상은 www.dankook.ac.kr 이였음. OS windows7 이다.

 

1)      ICMP(8byte + 32bytes(Data))

a)      Type : 8                                                                // Type 8 Echo (Ping) request 나타낸다.

b)      Code : 0                                                // Type ==8 && Code == 0 Echo (Ping) request 나타낸다.

c)       CheckSum(4bytes)                          // 데이터 오류를 체크

d)      Identifier(BE) : 1                               // Ping process ID 사용되어진다 BE Big-Endian 의미한다.

e)      Identifier(LE) : 256                           // Ping process ID 사용되어진다 LE Little-Endian 의미한다.

f)       Sequence number(BE) : 38          // Ping 순서를 의미한다 값은 1 증가하게 된다(몇번쨰 핑인지 있다)

g)      Sequence number (LE) : 2560     // Ping 순서를 의미하며 Little Endian방식으로 표현하였다.

h)      Data(32bytes)                                   // 아무 의미없는 데이터로 채워지며 windows 경우 alphabet으로 32bytes 채워진다.

2)      IPv4

a)      Version  : 4                                          // IPv4 나타낸다

b)      Header length : 20                           // 헤더의 크기를 나타낸다

c)       Service : 0x00                                     // Default service 나타낸다

d)      Total length : 60                                // Datagram 크기를 나타낸다, ICMP encapsulated 되었다.

e)      Identification : 0x7fe6                    // datagram ID 나타낸다

f)       Flags : 0x00                                         // 예약되어 있다.

g)      Fragment offset : 0                         // SYN packet Fragment offset 가질 필요가 없다.

h)      Time to live = 128                             // 보통 256으로 초기화 되며, Hop 지날때마다 한개씩 감소하게 된다.

i)        TYPE  = ICMP(1)                                                // ICMP 캡슐화 IP 헤더이다

j)        Checksum                                           // 2바이트의 Checksum, 오류 체크를 한다.

k)      Source IP addr 192.168.0.3           // Ping 요청한 자신의 IP주소이다

l)        Dest IP addr : 203.237.226.85      // 단국대 서버로 ping 테스트를 보았다.

 

3)      Ethernet(14 bytes)

a)      Destination(6bytes)                        // 수신자 MAC(Media access control) 주소를 나타낸다.

b)      Source(6bytes)                                 // 송신자 MAC 주소를 나타낸다

c)       TYPE : IP(2bytes)                              // IP Protocol 캡슐화한 Ehternet frame이다.

 

따라서 크기는 8(ICMP 헤더) + 32(ICMP Data part) + 20(IP header) + 14(Ethernet header) +
                                                8(Preamble) + 4(CRC) = 86 bytes
된다.

 


'Programming > Network Programming' 카테고리의 다른 글

TCP programming basis  (0) 2011.10.28
.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
get client IPadrress in server side  (0) 2011.10.10
Reference for unix socket api  (0) 2011.09.29
Posted by 박세범

Let's make a program whose both a server and a client send a data.

one data from the client to the server is "client"s address(IP+port #)

and the other data is a time information from a server to a client.

We need to take a look at the accept function carefully.

If accept method has a second parameter and third parameter, it will save struct sockaddr inside.

This is a server side source code

 

Server.c

#include <sys/types.h>            // 리눅스system call 관련헤더

#include <sys/socket.h>           // 리눅스소켓헤더

#include <arpa/inet.h>            // 인터넷관련헤더들

#include <stdio.h>                // 표준입출력라이브러리

#include <stdlib.h>               // strcmp 등을활용하기위한해더

 

int main(void)                           //     메인함수시작

{

       struct sockaddr_in local;  // server 주소정보를가질구조체선언

       struct sockaddr_in client; // client에게보내줄구조체선언

       int csize;                 // accept함수3번째인자에들어갈구조체의길이변수

       int s; int s1;       int rc;              // ssocket() 리턴, s1accept() 리턴rcrecv() 리턴값으로사용된다.

       local.sin_family = AF_INET; // 우리가사용하는Internet을의미한다.

       local.sin_port = htons(5300);            // port#5300으로예약되어있다.

       local.sin_addr.s_addr = htonl(INADDR_ANY);      // 어떤client든지다받겠다는의미이다.

      

       char getTime[255];                       // client로부터시간을받을데이터선언

 

       printf("\n\nA server has been started, the port number is reserved as 5300\n");

                                                // 서버시작메세지출력

 

       s = socket(PF_INET, SOCK_STREAM, 0);     // TCP를위한소켓생성

      

       if(s<0){                                 // 소켓생성실패시

              perror("socket call failed");     // 메세지를출력하고

              exit(1);                          // 프로그램종료

       }                                        // if문의끝

 

       rc = bind(s, (struct sockaddr *)&local, sizeof(local));       // port#IP를연계시켜준다.

       if(rc<0){                                              // Bind가실패하면

              perror("bind call failure");                           // 메세지를출력후

              exit(1);                                        // 종료한다.

       }                                                      // if문의끝

 

 

       printf("A server is waintg for a client request\n");   // client를기다린다는메세지를출력

 

       rc = listen(s,5);                                      // 5개의queue를생성한한다.

       if(rc){                                                       // 만약listen이실패하면

              perror("listen call failed");                   // 메세지를출력후

              exit(1);                                        // 프로그램을종료한다.

       }                                                      // if문의끝

 

       csize = sizeof(client);                                // csizesockaddr 구조체크기를나타낸다

 

       s1= accept(s,(struct sockaddr*)&client ,&csize);       // 2번째인자는client 주소를받을구조체, 3번째는그구조체크기를명시

                                                       // 이후우리는client 주소에대한정보를알수있다.

 

       printf("Conntection established!\n");    // 연결성공이라는메세지추력

 

       if(s1<0){                                // 만약accept가실패한다면

              perror("accept call failed");     // 메세지를출력후

              exit(1);                          // 프로그램을종료한다.

       }                                        // if문의끝

 

       rc = recv(s1,getTime ,sizeof(getTime), 0);      // client로부터시간을받는다.

 

       if(rc<=0){                               // 만약실패한다면

              perror("recv call failed");       // 메세지를출력후

              exit(1);                          // 프로그램을종료한다.

       }                                        // if문의 끝

 

       printf("------Current time from client : %s ----------\n", getTime);

                                                // 현재시간을출력한다.

 

       printf("A server will send a client's IP address \n");

                                                // client의주소를보낸다는메세지출력

 

       rc = send(s1, &client , sizeof(client), 0);            // client로자료를보낸다.

       if(rc <= 0)                              // 만약send가실패하면

       {                                        // if문시작

              perror("send call failed");       // 메세지를출력후

              exit(0);                          // 프로그램을종료한다.

       }                                        // if문의끝

       printf("The server will be closed soon \n\n");         // 서버를종료한다는메세지

       rc = close(s1);                                        // close함수호출

       if(rc < 0)                                             // 만약실패하면

       {

              perror("close failed");                         // 메세지를출력하고

              exit(0);                                        // 종료한다.

       }

       rc= close(s);                                          // socket() 또한종료한다.

       if(rc <0)                                              // 만약실패하면

       {

              perror("close socket failed");    // 메세지를출력후

              exit(0);                          // 프로그램을종료한다.

       }

       exit(0);                                 // 성공하면프로그램을종료한다.

}

 

 

 

 


Client side.


#include <sys/types.h>            // 리눅스system call 관련헤더

#include <sys/socket.h>           // 리눅스소켓헤더

#include <arpa/inet.h>            // 인터넷관련헤더들

#include <stdio.h>                 // 표준입출력라이브러리

#include <stdlib.h>               // strcmp 등을활용하기위한해더

#include <time.h>                 // 현재시간을받기위해필요한헤더

 

int main(char argc, char *args[])               // 메인함수는인자를받기위해서parameter를설정하였다.

{     

       struct tm *timeinfo;                     // 시간을저장할구조체

       time_t rawtime;                                               // rawtime을이용해서시간을구할것이다.

       struct sockaddr_in clientAddress;        // 서버로부터받을데이터의구조체

       struct sockaddr_in peer;                 // socket 생성시필요한구조체

       int s; int rc;                                  // ssocket descriptorrcflag 및받는데이터크기변수로사용

 

       if(argc != 3){                                                       // 만약서버주소와, port#를입력하지않았다면

              printf("Usage : client.out serverIPaddress serverPort#");     // 사용법을알려주고

              printf("Example : client.out 127.0.0.1 5300\n");              // 예를들어준다.

              exit(1);                                               // 그리고종료한다.

       }                                                             // if문의끝

      

       peer.sin_family = AF_INET;                      // Internet을위한''

       peer.sin_addr.s_addr = inet_addr(args[1]);             // argument2진수형태의ip로바꾼후저장한다.

       peer.sin_port = htons(atoi(args[2]));           // port번호역시int형으로바꾼후시스템방식으로맞춘다.

       memset(&peer.sin_zero,0,sizeof(peer.sinzero));  // sin_zero를모두0으로만든다.

 

       time(&rawtime);                                 // time을호출해서1960년이후초를받고

       timeinfo = localtime(&rawtime);                 // rawtime을이용해서local 시간을받고

       mktime(timeinfo);                               // ,,,,,초형태로바꿔준다.

       char currentTime[255];                          // 시간정보를currentTime으로바꿔준다.

       sprintf(currentTime, "Date ->  %dyr - %dm - %dd  time -> %dh:%dm:%ds",

                     timeinfo->tm_year+1900, timeinfo->tm_mon,

                     timeinfo->tm_mday, timeinfo->tm_hour,

                     timeinfo->tm_min, timeinfo->tm_sec);

                                                      // 구조체를string에대입한다. -----초순이다.

 

       printf("\n\nA client program has been started\n");            // 프로그램이시작됐음을알리는메세지

 

       s = socket(PF_INET,SOCK_STREAM,0);              // TCP 소켓을생성한다.

 

       if(s<0){                                        // 소켓생성실패시

              perror("socket call failed");            // 메세지를출력하고

              exit(1);                                 // 프로그램종료

       }                                               / if문의끝

 

       rc = connect(s, (struct sockaddr *)&peer, sizeof(peer));      // 서버와연결한다.

       if(rc){                                                       // 연결이실패하면

              perror("Connect call failed");                  // 오류메세지출력후

              exit(1);                                        // 프로그램을종료한다.

       }                                                      // if문의끝

 

       printf("A client has been connected to the server\n"); // 성공하면이메세지를뿌려준다.

 

       rc = send(s,currentTime , sizeof(currentTime), 0);            // 그리고현재시간을서버에게보낸다.

 

       if(rc <= 0){                                           // 만약보내는것이실패하면

              perror("send call failed");                     // 실패한다는메세지를보낸후

              exit(1);                                        // 나간다.

       }                                                      // if문의끝

 

       printf("A client sent a current time to the server\n");       // 전송이성공적으로됏으면이메세지를출력한다.

       rc = recv(s,&clientAddress,sizeof(clientAddress),0);   // 전송후서버로부터메세지를받는다.

                                                              // 2번째인자를보면수신을구조체로한다

      

       if(rc<=0)                                              // 전송이실패했을경우

              perror("recv call failed");                     // 메세지를출력한다.

       else{                                                  // 전송이성공했으면

              printf("------- client IP address received from server : %s  ----------- \n", inet_ntoa(clientAddress.sin_addr));

              printf("-------client port number received from server : %d -----------\n", htons(clientAddress.sin_port));

       }                                                             // 받은구조체를알맞게변환하게출력한다.      

       printf("The client will be closed \n\n");                            // 데이터를받은후client는종료한다.

       if(close(s)<0){                                               // 종료가비정상적이라면

              perror("closing socket failed");                       // 메세지를출력후

              exit(0);                                               // 프로그램을종료한다.

       }                                                             // if문의끝

       exit(0);                                                      // close가정상적이면다시종료한다.

}




'Programming > Network Programming' 카테고리의 다른 글

TCP packet and ICMP packet analysis  (0) 2011.10.28
.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
get client IPadrress in server side  (0) 2011.10.10
Reference for unix socket api  (0) 2011.09.29
Posted by 박세범

 shit.. I studied in a wrong way. I should've done something else

 but no regret because I've known a lot of network-programming Thank you for Dr. Cho.
Posted by 박세범
please take a look at accept() method,
second and third parameters must have values
don't forget

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    struct sockaddr_in local;
    struct sockaddr_in client;
    int *csize;
    int s;    int s1;    int rc; char buf[1];
    local.sin_family = AF_INET;
    local.sin_port = htons(5300);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
   
    char getTime[255];

    //added by Justin
   
    printf("A server has been started, the port number is reserved as 5300\n\n");


    s = socket(PF_INET, SOCK_STREAM, 0);
    if(s<0){
        perror("socket call failed");
        exit(1);
    }

    rc = bind(s, (struct sockaddr *)&local, sizeof(local));
    if(rc<0){
        perror("bind call failure");
        exit(1);
    }


    printf("A server is waintg for a client request\n\n");

    rc = listen(s,5);
    if(rc){
        perror("listen call failed");
        exit(1);
    }



    csize = sizeof(client);        // this is used to get a ip address using accept()

    s1= accept(s,(struct sockaddr*)&client ,&csize);    // we need to know the ip address of a client
    // to get client address. then we have to send this client
    // address to the client.

    printf("Conntection established!\n\n");

    if(s1<0){
        perror("accept call failed");
        exit(1);
    }

    rc = recv(s1,getTime ,sizeof(getTime), 0);    // rc return the size of the data

    if(rc<=0){
        perror("recv call failed");
        exit(1);
    }

    printf("\nCurrent time from client : %s \n", getTime);        //print current Time

    printf("\n\nA server will send a client's IP address \n");

    rc = send(s1, &client , sizeof(client), 0);        // send a structure of sockaddr_in to the client
    if(rc <= 0)                        // if it failes
    {
        perror("send call failed");
        exit(0);
    }
}





'Programming > Network Programming' 카테고리의 다른 글

TCP programming basis  (0) 2011.10.28
.. no regret..  (0) 2011.10.26
get client IPadrress in server side  (0) 2011.10.10
Reference for unix socket api  (0) 2011.09.29
TCP/IP  (0) 2011.09.21
Posted by 박세범
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    struct sockaddr_in local;
    struct sockaddr_in client;
    int *csize;
    int s;    int s1;    int rc; char buf[1];
    local.sin_family = AF_INET;
    local.sin_port = htons(5300);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
   
    char getTime[255];

    //added by Justin
   
    printf("A server has been started, the port number is reserved as 5300\n\n");


    s = socket(PF_INET, SOCK_STREAM, 0);
    if(s<0){
        perror("socket call failed");
        exit(1);
    }

    rc = bind(s, (struct sockaddr *)&local, sizeof(local));
    if(rc<0){
        perror("bind call failure");
        exit(1);
    }


    printf("A server is waintg for a client request\n\n");

    rc = listen(s,5);
    if(rc){
        perror("listen call failed");
        exit(1);
    }



    csize = sizeof(client);        // this is used to get a ip address using accept()

    s1= accept(s,(struct sockaddr*)&client ,&csize);    // we need to know the ip address of a client
    // to get client address. then we have to send this client
    // address to the client.

    printf("Conntection established!\n\n");

    if(s1<0){
        perror("accept call failed");
        exit(1);
    }

    rc = recv(s1,getTime ,sizeof(getTime), 0);    // rc return the size of the data

    if(rc<=0){
        perror("recv call failed");
        exit(1);
    }

    printf("\nCurrent time from client : %s \n", getTime);        //print current Time

    printf("\n\nA server will send a client's IP address \n");

    rc = send(s1, &client , sizeof(client), 0);        // send a structure of sockaddr_in to the client
    if(rc <= 0)                        // if it failes
    {
        perror("send call failed");
        exit(0);
    }
}


accept should have the sockaddr struct as long as we want to know about client's address information
In this example, client.sin_addr has a IP address of a client and client.sin_port has a port #


'Programming > Network Programming' 카테고리의 다른 글

.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
Reference for unix socket api  (0) 2011.09.29
TCP/IP  (0) 2011.09.21
The concept of TCP/IP part 1.  (2) 2011.09.07
Posted by 박세범


Prototype

Return value

Parameter

The role of function

int socket(int domain,
int type int protocol)

양의 정수 : socket descriptor
-1 :
소켓 생성 실패

domain : PF_INET: protocol type
                 PF_INET6 : IPv6
                  PF_UNIX : UNIX
방식의 프로토콜
type : SOCK_STREAM : TCP
           SOCK_DGRAM : UDP

           SOCK_RAW : raw(ICMP)
protocol : IPPORTO_TCP
                  IPPROTO_UDP
                  0(for TCP, UDP)

새로운 소켓을 만들 쓰이며, 반드시 return 값을 가지고 있어야 한다. Return 값은 추후 소켓을 구별 하는대 쓰인다.

함수는 bind() or connect() 함께 쓰인다.

int close(int socket)

0 : 소켓 종료가 정상적으로 이뤄짐
-1 :
소켓 종료를 실패함

socket : socket()에서 만들어진
               socket desrtiptor

소켓을 종료할 쓰이며, 상당시간 동안
time_wait
상태를 유지함에 유의하자.

int bind(int socket,
const struct sockaddr *localaddr
int addrlen)

0 : bind 성공했을 경우
-1 : bind
실패했을 경우

socket : socket() return
localaddr :
서버의 주소를 가진 구조체, 대게 sockaddr_in
addrlen :
구조체의 크기

서버 프로그램이
sock
에게 port(이름) 할당(등록) 한다.

int listen(int socket, int queuesize)

0 : 성공했을 경우
-1 :
실패 했을 경우

socket : socket() 의핸 return socket descriptor
queuesize : queue
최대크기
                    
최대는 5이다

생성된 소켓이 client 연결을 기다리는 함수
queue
최대 길이를 설정한다.

int accept(int socket,
struct sockaddr *caddress
int *caddresslen)

-1 : 실패했을 경우
양의정수 : socket I/O 위한
non-negative descriptor
반환

socket :  socket() return
caddress : sockaddress_in
구조체 포인터,
                   client address
저장된다.
caddresslen : sockaddress_in
구조체의 길이의 포인터

Queue 들어있는 처음 연결을 추출하는 함수, 만약 queue 비어있다면 blocking 된다.
client
로부터 연결요청을 받아 통신을 위한
새로운 소켓을 생성한 연결한다.

int connect(int socket,
const struct sockaddr *serveraddress
int serveraddresslen)

0 : 성공했을 경우
0
아닌 정수값 : 실패할 경우

Socket : socket() return
serveraddress :
서버주소를 가지고 있는
                           
구조체의 포인터
serveraddresslen :
서버주소를 가지고 있는
                                 
구조체의 길이

Socket 다른 socket 연결한다.
서버와의 통신을 위해 통신 연결을 요청하며 주로
client
쪽에서 행에진다. 3way-handshaking
이때 발생한다.

int send(int socket, const char* data
int length, int flags)

-1 : 실패했을 경우
the # of byte :
성공했을 경우

Socket() : accept()에서 만들어진 descriptor
data : 
보내고 싶은 data
length : data
길이(byte)
flags :
대게 0으로 설정

상대방 프로그램에게 데이터를 송신한다.
만약 성공했을 경우 data TCP buffer 전송되었다는 것을 의미하며
전송 버퍼에 저장된 데이터는 ACK메세지를 수신하면서 삭제된다.


int recv(int socket, char*data,
int length, int flags)

Buffer 읽힌 byte
-1 :
에러가 생길 경우
0 :
접속종료를 알림

Socket : accept()에서 만들어진 descriptor
data :
수신받는 data
length : data
길이
flags :
대게 0으로 설정

Protocol(i.e : TCP) buffer 읽는 byte 읽는 함수이다.
stream
형식의 byte 읽는 것에 유의해야 하며 첫번째 parameter socket file descriptor(accept() 반환값)
임에 유의해야 한다.

int sendto(int socket, char* data,

Lint length, int flags,
struct sockaddr *destaddress,
int addresslen)

the # of byte : 성공했을 경우
-1 :
실패했을 경우

socket : accept() return
data :
원하는 data

length : data 길이
flags :
대게 0으로 설정
destaddress :
목적지의 address 가지고
                        
있는 구조체의 포인터
addresslen : destaddress
크기

Datagram 스타일의 전송방식으로써(datagram socket 다른 remote host 보지 못한다) 패킷을 전송하고
수신할 연결되지 않은 소켓을 통해 송신한다.
따라서 패킷을 보내기 destaddress 구조체를
이용하여 전송한다.

int recvform(int socket, char*data, lint length, int flags,
struct sockaddr *srcaddress,
int *addresslen)

Buffer 읽힌 byte
-1 :
에러가 생길 경우
0 :
접속종료를 알림

socket : accept() return
data :
원하는 data

length : data 길이
flags :
대게 0으로 설정
destaddress :
수신자의 address 가지고 있는
                         
구조체의 포인터
addresslen : destaddress
크기

Sendto() 형식과 같으며, 단지 receive() 하는
역할만이 다르다.

int setsockopt(int socket, int level,
int opt, const char* optval,
int optlen)

0 : 성공했을 경우
-1 :
실패했을 경우

Socket : socket() 반환값
level : SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP
optval :
level == SOL_SOCKET ?
              SO_REUSEADDR  - IP addr/port
재사용
               SO_KEEPALIVE –
주기적 연결상태 확인
               SO_BROADCAST -
방송 전송 허용
               SO_LINGER - Closesocket()
처리 방식
               SO_SNDBUF -
송수신 버퍼 크기 설정

               SO_SNDTIME - 송수신 함수 타임아웃
level == IPPROTO_IP ?
               IP_TTL – TTL
설정

            IP_HDRINCL – 헤더 포함 전송
            IP_MULTUCAST_IF :
다중전송

 

생성된 소켓의 옵션을 설정하는 함수이다.

Parameter level opt 따라 결과 값이 바뀌게 된다.



int getsockopt(int socket, int level,
int opt, const char* optval,
int optlen)

0 : 성공했을 경우

-1: 실패했을 경우

setsockopt() 함수와 기본적으로 옵션이 같으며
opt
level 지정하면 원하는optval
값을 얻을 있다

소켓옵션을 확인하기 위한 함수이며, optval 값을 읽어드리며, 포인터로 지정한 변수에 값이 읽히게 된다.

struct hostent *gethostbyname(const char *name)

Struct hostent : 성공 했을 경우
서버에 관한 정보들이 구조체에 들어가게 된다.
NULL :
실패할 경우.

name : domain명을 적으면 된다.
             i.e) www.naver.com

도메인의 이름을 (ie. naver.com) 네트워크 바이트로
정렬된 2진수 IP주소로 변환한다. IPv6와의 호환성
때문에 최근에는 getaddrinfo() 혹은 getnameinfo() 쓴다

 

struct hostent *gethostbyaddr(const char *addr, int len, int type)

 

Struct hostent : 성공 했을 경우
서버에 관한 정보들이 구조체에 들어가게 된다.
NULL :
실패할 경우.

addr : IP 주소
len : IP
주소의 길이
type : IP
주소 type

이진수 IP주소를 도메인 이름으로 바꿔준다. 기본적인 개념은 gethostbyname()함수와 같다.


 

char *inet_ntoa(struct in_addr in);

int inet_aton(const char *cp,
struct in_addr *inp);

inet_ntoa()
     ip
주소 형태의 string 반환
 
 inet_aton()
     Non-zero :
주소가 valid 경우
     0 :
주소가 틀렸을 경우      

in : struct in_addr (ip주소를 담고 있는 구조체)
cp :
문자열 형태의 address
inp :
문자열 형태의 address IP형태로 변환할
        
저장될 struct in_addr 구조체

Number -> address, address -> number
변환이 필요할 쓰이며, 현재는 IPv6와의 호환성 때문에 inet_ntop() inet_pton()으로 대체되었다.

 

in_addr_t inet_addr(const char *cp);

 

주소 정보를 가지고 있는
in_addr_t
구조체를 반환한다.

cp : address 문자열

기본적으로 inet_aton() 함수와 같으며, 매우 오래된 method 쓰이지 않는다.

struct servent *getservbyname(                                                const char *name,                                            const char *proto)

 

servent  구조체가 반환되며, 만약 proto 값이 NULL 경우 protocol match되는 servent 구조체가 반환된다.

0 : 실패할경우 0 반환한다

name : servce 이름을 쓴다(program)
proto :
프로토콜 type 쓴다(TCP or UDP)

Parameter 주어진 이름과 프로토콜이 match되는
service
정보를 찾아서 정보를 가진servent 구조체로
반환하는 함수이다.

 

struct servent *getservbyport(int port, const char *proto);

 

servent  구조체가 반환되며, 만약 proto 값이 NULL 경우 protocol match되는 servent 구조체가 반환된다.

0 : 실패할경우 0 반환한다

port : 원하는 port # 쓴다.
proto : protocol type
쓴다(TCP or UDP)

 

기본적인 parameter getservbyname() 같다.

Paramter 주어진 port proto 매치되는 service정보를 찾아서 정보를 servent 구조체로 반환하는 함수이다.

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

 

함수는 변환된 값을 반환한다.
uint32
4byte 의미하며
unint16
2byte 의미한다.

hostlong :  host long type 데이터
hostshort : host
short type 데이터
netlong : network
long type 데이터
netshort : network
short type 데이터

h : host 의미한다

to : converting 의미한다
n : network
의미한다
l,s :
데이터형을 의미한다
        (long or short)

host byte order로부터 network byte order

multi-byte integer type형식으로 변환한다.

(역도 성립한다, vice versa)

 

함수는 hardware 호환성 때문에 만들어 졌는데, 시스템 마다 각기 다른식으로 byte order 저장하기 때문에 port # 숫자를 네트워크로 전송 했을 경우 함수들을 써야한다.




struct for network-programming(네트워크 프로그래밍을 위한 구조체)

 

1.        struct sockaddr
{
    u_short sa_family;    /* address family */
    char sa_data[14];     /*
주소(IP 주소포트 번호) */
};

 

2.        struct in_addr            /* sockaddr_in 안에 정의되어 있음에 유의하자 */
{
    u_long s_addr;    /* 32
비트의 IP 주소를 저장할 구조체 */
}

 

3.        struct sockaddr_in
{
    short sin_family;            /*
주소 체계 */
    u_short sin_port;           /* 16
비트 포트 번호 */
    struct in_addr sin_addr; /* 32
비트 IP 주소 */
    char sin_zero[8];           /*
전체 크기를 16바이트로 맞추기 위한 dummy */
}


 

 

4.        struct hostent

{

    char *h_name            /*   host 이름 */

    char **h_aliases            /*  aliases(별명?) list , 마지막 요소는 항상 NULL이다 */

    int h_addrtype            /* address 형식 AF_INET 인터넷 주소 체계이다 */

    int length                    /* address 길이, byte단위 이다 */

    char **h_addr_list             /* IP주소의 list들이 있으며, struct in_addr* 가리키는 pointer이다.

}      

 

5.        struct servent
{

        char    *s_name;        /* 공식적인 service 이름*/

        char    **s_aliases;    /* alias(별명?) list */

        int     s_port;         /* port 번호 */

        char    *s_proto;       /* 사용하고 있는protocol  */
}


'Programming > Network Programming' 카테고리의 다른 글

.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
get client IPadrress in server side  (0) 2011.10.10
TCP/IP  (0) 2011.09.21
The concept of TCP/IP part 1.  (2) 2011.09.07
Posted by 박세범

 Well. the reason why TCP/IP is very important is because that's the most common protocols now.

Let's take a look at the difference btw TCP and IP

Firstly IP is in a network layer, what's the purpose of this? it's a communication btw a computer and a computer
the answer why we use IP is because MAC cannot see other networks, that's why people need to make one
address that is able to look at other network's computers. THat's why IP came out.

In transport layer(Layer 4), there is one protocol named TCP.
TCP has some features as below.
  1) a communication btw apps and apps
  2) how do we know about app #? : using port number
  3) End to End, communication protocol... : it means using port, applications will reach to each other.

What's the roles of TCP?
   1) TCP is in Transport layer( #4 layer)
   2) Reliable data transmission
   3) End-to-end protocol
   4) Stream interface -> but the unit is a segment?
         -> What's stream? -> transmission by byte to byte.. when application will send a packet, it does not go to
             TCP segment directly, it goes to TCP buffer... the thing is TCP is variable that's why we do not know
             what size of data is coming. APP -> TCP buffer -> TCP -> Segment <-- converting
   5) connected oriented protocol : three ways hand shaking (very important, will be mentioned later)
   6) Full-duplex communication : it has both "direction" and "동시성(I don't know how to say)

End to End service : easily, it means an application of a host A is communicating with an application of host B
                             Connection -> Data sending -> Disconnecting.. think like a telephone
                             but TCP is just a virtual mechanism

How to be capsulated for TCP?

Frame(Ethernet) header + Datagram(IP) header + Segment(TCP)

TCP segment header 

1)     Source port(16bit) : 송신자의port넘버를 알기 위해서 정의된 field이다.

2)     Destination port(16bit) : 수신자의port 넘버를 알기 위해서 정의된 field이다.

3)     Sequence number : 2가지 역할을 하는데 SYN field값에 따라 다르다

a.      SYN == 1? : 이는initial sequence number로써, 처음 data byte Ack number 사용되어 진다. 이후 값들이 sequence 따라 1 증가하게 된다.

b.      SYN == 0?: 첫번째data byte  축적된 sequence number 의미한다.

4)     Acknowledgment number(32bit) : 만약 ackflagset 이라면, 값은 다음sequence number 의미한다. 상대방으롭터 다음 전송 때에 받기를 기대하는 첫째 바이트 번호이다.

5)     Data offset(4bit) : TCP header 크기를 구제화 시키는 field이다. Words(4byte) 단위로 구성되며 최대 20~60 byte까지 구성될 있다.

6)     Reserved (6bit): 미래에 사용될 것을 대비해서 착안됐으며, 0으로 set되어야 한다.

7)     Fags(6bit) : 6bits 구성되어 있으며,1bitflag 가지고 있다. 종류는 아래와 같다.

a.      URG flag : 긴급 상황이 발생했을 경우 사용된다.

b.     ACK flag : 전송된 값이 valid(유효함) 알리는데 사용된다.

c.      PSH flag : 버퍼가 차지 않았더라도, flag set이라면 바로 데이터를 전송한다.

d.     RST : 재설정(re-setting) 요구하는 flag이다.

e.     SYN : 3-way handshaking(Syn -> ack -> Syn 순서) 제의하는 flag이다.

f.       FIN : Session 종료하고자 사용한다.

g.      Window Size(16bit) : 현재 상태의 최대 버퍼크기를 말하는field이다.

h.     CheckSum : 데이터가 유효한 것인지, 이상이 없는지 확인하는field이다

i.        Urgent Pointer : 긴급한 데이터를 사용해야 데이터가 존재하는 곳을 가르키는 포인터 값이다.



 
  

'Programming > Network Programming' 카테고리의 다른 글

.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
get client IPadrress in server side  (0) 2011.10.10
Reference for unix socket api  (0) 2011.09.29
The concept of TCP/IP part 1.  (2) 2011.09.07
Posted by 박세범
       
       
       
       
       
       


 From today, I am going to review all my studies at Dankook.
Today's topic is TCP/IP, which is the basis of network programming.

The teacher is Dr. 조경산. He is a excellent teacher =)

Basically, we need three elements, a sender, a receiver and a thing that connects between them
 so that network will work

What's the computer communication?
   : the computer, which equals with a receiver and sender or something related to computer.

 The important thing is why the computer communication has come out.
  1) Direct connection : just like word itself, it connects btw two computers directly by using a wire or physical stuff.
  2) Indirect connection : connecting all computers with a lot of networks, basically networks are connected.

 Direct connection costs a lot of money since everything would have to be closer and it also has a distance problem.

So, in order to do the indirect connection, we would have to make a rule so that all datas should have been sended and received perfectly against the direct connections.

we call the rule "protocol"

The definition of protocol is "a rule that is accepted in order to communicate between computer systems"
it consists of syntax, semantics, and timing.
syntax : the level of signal or data type.
semantics : the information for handling exceptions and each communications
timing : corresponding data speed and make an order


Now, important thing is "OSI7 layer protocol", which is a bit different from TCP/IP protocol

OSI 7 layer

Application(7)
Presentation(6)
Session(5)
Transport(4)
Network(3)
Data Link(2)
Physical(1)

However, TCP/IP has five layers.

application(5)
transport(4)
internet(3)
network interface(2)
physical(1)

since physical layer only hands the data transfer, we sometimes merge layer 1 and layer 2 as "network interface" itself.

We all data 'Packet' in network computing. but each layer has a different term indicating "Packet"
Network interface(2) -> frame
internet(3) -> Datagram
Transport(4) -> Segment.

Why we use TCP/IP? it's because..
"in order to treat internet easily.." is there anything more persuading than this?

based on OSI 7 layers concept, each layer except for physical layer will put one header each in the data.

 Layer 2
header
 Layer 3
header
Layer 4
header
 Layer 5
header
 Layer 6
header
  Layer 7
header
data


Well let's see "network interface layer(2)"

there is a Ethernet which is commonly used in Layer 2.

The structure of frame(= packet, called as "frame" in network interface layer.

Preamble
DA
SA
length
Data type
Data
CRC
IEEE 802.3 ethernet frame type

  Well. the structure is not a original data. it's been added with "header!" see a lot of headers, Preamble, DA, SA stuff like that.  look at the DA(Destination address)... what kind of address we use? IP? nope...
we use MAC(Media Access control address), which is a unique number of NIC(Network interface Card).
why do we use MAC? Layer 2 only cares about just one Network inside.
If there was no MAC, all data in one network would be sent to all computers in one network.
That's why we need MAC in order to look at the destination of the computer which we are supposed to send.

Loot at the CRC located in the end of a frame.
What's CRC firstly? -> Cyclic redundancy check, an error-detecting code designed to detect accidental changes to raw comtpuer data Wikipedia said.

Well. the thing why we need this is because Layer 1(physical) only care about transmitting all data bit by bit
in hardware perspective, the CRC must be handled in NIC(network interface card). it's more likely physical perspective.

lastly, take a look at length part. why do we need length? because.. there is no way how the computer would know
the length of a data. That's all.

let's move on the layer 3(internet layer).
we will see the concept of IP..
why did IP come out? it's because there was a problem between networks.
each network needed to transmit data to one another. but the thing is the media is different, form of frame is different..
that's why people though of making one virtual network which contains all networks.(let's see all networks as one network)

You know what?
All computers connected to the internet is connected to another network.(do you agree?)

as you know internet is a set of a lot of network. IP is the address which is uniquely possessed by a computer which
is connected to the internet.

now, there is new packet coming out, data gram...
IP is just one kind of protocols which defines the path of a destination from a sender.

Let's think about the difference btw MAC and IP(Internet protocol) addresses..
again, MAC is only used in one network inside, but IP is used from a network to network. Tha'ts the different.


What is the purpose of the internet? : virtual single communication system

 -> All hosts must use the same manner to make an address.
 -> the address must be unique
 -> IP address : independent address indicated(networks only recognize MAC address)
 -> usually 32 bit but IPv6 is 128 bits these days.. there is prefix and suffix.
in datagram header(it could be maximum 6k bytes(20+4n byte(header) + data)

there is one element of the header, TTL = Time to leave... -> why?
if a datagram(I mean packet) missed the way where it's supposed to be, then check the TTL in each network
net if the length is "1"?(from 255) then just throw it away because it took too long!

also there is CHECKSUM... it is implemented by a system.

Encapsulation.. you know the header will be put from Layer 5 to Layer 1 in Sender
and a destination take each one off from layer 1 to layer 5

ICMP(Internet Control Message Protocol)

IP has one characteristic.. which is best-effort, no matter what situations are, it doesn't matter
the purpose of IP is to transmit a data from sender to a receiver that's all.
it sometimes causes a error" but it doesn't matter

ICMP is purposed for the situation if IP layer(internet layer) has a problem in communications then
send a error msg to a destination.

so IP should be used with ICMP for handling errors..

'Programming > Network Programming' 카테고리의 다른 글

.. no regret..  (0) 2011.10.26
The example of one server that sends a client ID  (0) 2011.10.15
get client IPadrress in server side  (0) 2011.10.10
Reference for unix socket api  (0) 2011.09.29
TCP/IP  (0) 2011.09.21
Posted by 박세범