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