This might be really helpful for system programming(2011-fall semester) assignment at Dankook.


I am sure that somebody is struggling with understanding and pipe system call(Maybe Dankook students?)

Well.. Yes, it's hard  and Shell must have at least three functions.

1. Redirection
2. Pipe
3. Background

This post will talk about how to implement pipe basically, but in order to understand this correctly
you might need to practice it a lot. For me it took almost 4~5 hours to understand each function of dup2() and pipe()
Before begin this, I would like to share really good lecture website for those functions.

http://web.eecs.utk.edu/~huangj/cs360/360/notes/Dup/lecture.html
http://web.eecs.utk.edu/~huangj/cs360/360/notes/Pipe/lecture.html


Unfortunately, the official website which describes system calls in Linux does not give us enough information
so that we implement those functions practically. so I would like to explain this a little bit more easily than it.

Well.

Firstly, we need to understand what the pipe is

What's pipe? yes, pipe is a kind of path between one process and process.
since a process(program in execution) is strictly prohibited to share a data. there is no way to communication with each other. That's why we use a pipe.

The prototype of pipe() system call is this

int pipe(int pipefd[2]);

Make sure the parameter of pipe() system call is int pipefd[2]
fd means file description. Yes, pipe use a file description for each communication.

The official description is as below

pipe() creates a pipe, a unidirectional data channel that can be used for interprocess communication. The array pipefd is used to return two file descriptors referring to the ends of the pipe. pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe. Data written to the write end of the pipe is buffered by the kernel until it is read from the read end of the pipe. For further details, see pipe(7).


However, what the fuck that mean? okay. let's make it simple.
Pipe is used for the communication tool by making two more file descriptions,
which is fd[0] and fd[1] fd[0] is used for reading(like STDIN) and fd[1] is used for
writing(like stdout)

as long as we use pipe system call with fork(), the structures will be like this..

pipe1(parent)     file                                        pipe1(child)
|----------|      desc-                                       |----------|
| code,    |     riptors                                      | code,     |
| globals, |                  |---------|                     | globals, |
| heap.    |       0 <-----   |         |  -----> 0           | heap.    |
|          |       1 ----->   |operating|  <----- 1           |          |
|          |       2 ----->   | system  |  <----- 2           |          |
|          | pipefd[0] <---   |         |  ---> pipefd[0]     |          |
|          | pipefd[1] --->   |---------|  <--- pipefd[1]     |          |
|          |                                                  |          |
| stack    |                                                  | stack    |
|----------|                                                  |----------|

from http://web.eecs.utk.edu/~huangj/cs360/360/notes/Pipe/lecture.html

well. before using pipe, we used only "STDIN, STDOUT, STDERR", however we have two more FDs
that are used for a kernal path between parent task and child task.

then we could use "dup2" function which duplicate a file description
We are gonna use dup2() function. The prototype is this.
int dup2(int fd1, int fd2)

what if we declare like "dup2(STDOUT,fd)"???????????????????
it means whenever STDOUT happens, the file description will be replaced instead of STDOUT,
DO NOT BE CONFUSED. We can use both file description STDOUT and FD however even if you use
STDOUT, all output datas will automatically be controlled by the file description.
that means you cannot see any STDOUT result, because all datas go to the file that is pointed by
FD!

Let's look at the example.

int main(void)
{
	int pfd[2];			// 0 for reading, 1 for writing.
	int pid;
	int pid2;
	char buf[10];
	int readSize;
	pipe(pfd);			// make a pipe;
	if( (pid = fork()) == 0)
	{
		close(pfd[0]);
		dup2(pfd[1],1);
//		close(pfd[1]);
//		open("a.txt",O_RDONLY, 0664);
		execlp("more","more","a.txt",(char*)0);
			// call more
		// child precessing
		//
	}
	
	else		// parent processing
	{
		if((pid2=fork())==0)
		{
			close(pfd[1]);
			dup2(pfd[0], 0);
//			close(pfd[0]);
			printf("does it work?");
			execlp("wc","wc",(char*)0);
		}
		else
		{
			wait();
			printf("Succedded");
		}
	}
}


This program is the same as "more a.txt | wc"
See? using pipe and dup2 all stdout goes to the "wc" task by using fd[1](for writing)
and the wc program reads all data from more process by using "STDIN with fd[0]"

we might be confused because dup2 and pipe function are too complicated.
in order to understand this processing, I suggest you draw a status of task structure.

=)

'Programming > System programming' 카테고리의 다른 글

custom cp sheel command with the mode information  (0) 2011.10.15
sys/types.h  (2) 2011.10.10
Posted by 박세범


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 박세범