Programming2012. 11. 18. 02:57


프로젝트를 뛰다보니, 당장 결과물을 내기에 급급하여 기초도 없이 작업하는 경우가 있다.

특히 Web이 그러한데.. Spring과 javascript 그리고 ajax에 관한 책을 단 1page도 보지않고..

구현하기에는 너무 무리가 있다. 여튼 이번에는 Spring에서 있는 annotatino 방식인 @ReponseBody에

대해서 적어볼까 하낟.


먼저 web-controller 부분은 


 @RequestMapping(value="/ajaxSelectBoardListCnt", method = RequestMethod.POST)

    public @ResponseBody ClassData chkAdmLogin () throws Exception   {

         

        ClassData data = new ClassData();

        data.setData("Testing");

        data.setVersion(true);

        System.out.println("Here we go");

        return data;

    }


servlet.xml에는 다음과 같이 추가한다.

1. beans :

xmlns:mvc="http://www.springframework.org/schema/mvc"

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd


2.  <context:component-scan base-package="com.samsung.abi" />


3. javascript 함수는 아래와 같이 만든다.


function doAjaxBoardListCnt() {

    $.ajax({

        url: "ajaxSelectBoardListCnt",

        type:"POST",

        //dataType: "application/json",

        //contentType: "text/plain; charset=euc-kr",

        success: function(data) {

            if(data != null)    {

            alert(data.version);

        //        $("#RsltTblAjax").html(data);

            } else {

          //      $("#RsltTblAjax").html("null 입니다.");

            alert('hello');

            }

        }

    });

}

끝. 간단하다.


Get으로 하고싶으면 그냥 post부분을 GET으로 바구면 떙

'Programming' 카테고리의 다른 글

Open SSH Server  (0) 2012.10.08
Being fillled circle / Android programming / Thread example  (0) 2011.10.15
File copy by using windows API  (0) 2011.08.31
Win32 API tutorial  (0) 2011.08.26
Posted by 박세범
Programming2012. 10. 8. 14:47

How to open SSH server on Ubuntu


OpenSSH Server

Introduction

This section of the Ubuntu Server Guide introduces a powerful collection of tools for the remote control of networked computers and transfer of data between networked computers, called OpenSSH. You will also learn about some of the configuration settings possible with the OpenSSH server application and how to change them on your Ubuntu system.

OpenSSH is a freely available version of the Secure Shell (SSH) protocol family of tools for remotely controlling a computer or transferring files between computers. Traditional tools used to accomplish these functions, such as telnet or rcp, are insecure and transmit the user's password in cleartext when used. OpenSSH provides a server daemon and client tools to facilitate secure, encrypted remote control and file transfer operations, effectively replacing the legacy tools.

The OpenSSH server component, sshd, listens continuously for client connections from any of the client tools. When a connection request occurs,sshd sets up the correct connection depending on the type of client tool connecting. For example, if the remote computer is connecting with the sshclient application, the OpenSSH server sets up a remote control session after authentication. If a remote user connects to an OpenSSH server withscp, the OpenSSH server daemon initiates a secure copy of files between the server and client after authentication. OpenSSH can use many authentication methods, including plain password, public key, and Kerberos tickets.

Installation

Installation of the OpenSSH client and server applications is simple. To install the OpenSSH client applications on your Ubuntu system, use this command at a terminal prompt:

sudo apt-get install openssh-client

To install the OpenSSH server application, and related support files, use this command at a terminal prompt:

sudo apt-get install openssh-server

The openssh-server package can also be selected to install during the Server Edition installation process.

Configuration

You may configure the default behavior of the OpenSSH server application, sshd, by editing the file /etc/ssh/sshd_config. For information about the configuration directives used in this file, you may view the appropriate manual page with the following command, issued at a terminal prompt:

man sshd_config

There are many directives in the sshd configuration file controlling such things as communications settings and authentication modes. The following are examples of configuration directives that can be changed by editing the /etc/ssh/ssh_config file.

[Tip]

Prior to editing the configuration file, you should make a copy of the original file and protect it from writing so you will have the original settings as a reference and to reuse as necessary.

Copy the /etc/ssh/sshd_config file and protect it from writing with the following commands, issued at a terminal prompt:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.original
sudo chmod a-w /etc/ssh/sshd_config.original

The following are examples of configuration directives you may change:

  • To set your OpenSSH to listen on TCP port 2222 instead of the default TCP port 22, change the Port directive as such:

    Port 2222

  • To have sshd allow public key-based login credentials, simply add or modify the line:

    PubkeyAuthentication yes

    In the /etc/ssh/sshd_config file, or if already present, ensure the line is not commented out.

  • To make your OpenSSH server display the contents of the /etc/issue.net file as a pre-login banner, simply add or modify the line:

    Banner /etc/issue.net

    In the /etc/ssh/sshd_config file.

After making changes to the /etc/ssh/sshd_config file, save the file, and restart the sshd server application to effect the changes using the following command at a terminal prompt:

sudo /etc/init.d/ssh restart
[Warning]

Many other configuration directives for sshd are available for changing the server application's behavior to fit your needs. Be advised, however, if your only method of access to a server is ssh, and you make a mistake in configuringsshd via the /etc/ssh/sshd_config file, you may find you are locked out of the server upon restarting it, or that thesshd server refuses to start due to an incorrect configuration directive, so be extra careful when editing this file on a remote server.

SSH Keys

SSH keys allow authentication between two hosts without the need of a password. SSH key authentication uses two keys a private key and apublic key.

To generate the keys, from a terminal prompt enter:

ssh-keygen -t dsa

This will generate the keys using a DSA authentication identity of the user. During the process you will be prompted for a password. Simply hitEnter when prompted to create the key.

By default the public key is saved in the file ~/.ssh/id_dsa.pub, while ~/.ssh/id_dsa is the private key. Now copy the id_dsa.pub file to the remote host and appended it to ~/.ssh/authorized_keys2:

cat id_dsa.pub >> .ssh/authorized_keys2

Finally, double check the permissions on the authorized_keys2 file, only the authenticated user should have read and write permissions. If the permissions are not correct change them by:

chmod 644 .ssh/authorized_keys2

You should now be able to SSH to the host without being prompted for a password.


간단하다 apt-get install openssh-server 만해도 끝나는듯

port를 변경하려면 root권한 획득후, /etc/ssh/sshd_config 를 열어서 port 부분을 변경해주면 된다.

ssh key 바꾸고 싶으면 아래의 절차에 따라서 진행하면 된다. 끝.

Posted by 박세범
Programming/Perl2012. 10. 5. 02:44



Chapter 04. 사용자 함수



함수의 이름 ? → & 기호가 붙는다.


사용자 함수를 만드는 법에 대해서 알아보자.


Sub NAME

{

}


Call ? → &NAME; 간단하네

& <-- 이걸 생략할 수 있지만, 만약 함수의 구현이 뒤쪽에 되어 있을 경우, &를 반드시 명시해 주어야 한다.

&를 구분하지 않을 경우 이것이 System Library Func인지 아니면 User Function인지 구분하긴 쉽지 않을듯..


use strict pragma를 쓴다 좋은 프로그래밍 습관을 강제적으로 적용받는다.


my는 scope variable을 지정할 때 쓰면 된다.

사용방법은 my ($what, @array) = @_;

이런식으로~?


subroutine func같은 경우 return값은 가장 마지막 연산..

return을 명시해줘도 되는데 귀찮으닌깐 안쓰는게 최고당 ^^;



Chapter 05. 입력과 출력


Linux의 대표적인 3가지 입출력 STDIN, STDOUT, STDERR


$line = <STDIN>

chomp($line)

보통 표준입력을 이렇게 받지만..

if you feel annoyed


chomp($line = <STDIN>)


Diamond operator... <-- Larry 딸내미가 지어줬다고 함..


command line 부분 argument 처리하기

@ARGV ← 인자를 읽어들인다.

ex ) foreach(@ARGV) print


Array를 Interpolation할 때

if print @array <-- 그냥 한줄씩 출력

print "@array" 한칸 띄어진다. 왜? 그렇게 만들었어요



File을 open할는 open method를 이용

open CONFIG, “<dino”


특수문자의 의미는 아래와 같다.

< : Input

> : Output

>> : If file exists, it will add strings(characters)


Perl 5.6?


open CONFIG, “<”, “dino


die Method? → kill the program with the log from $!

Warn is practically same with Die however, it does not close a program.




Print FileHandle “blablabla~~~”


input task using Diamond operator



./a.pl ab cd def

while(<>)

{

print

}

argv에 있는 것들을 읽어 그것을 출력한다



오늘 공부 끄읕~ ^^


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

Perl 프로그래밍 기본 셋팅  (0) 2012.10.04
Posted by 박세범
Programming/Perl2012. 10. 4. 15:05

과제를 위해서 현재 Perl을 공부하고 있다.

책은 Learning Perl 5/e 번역본 책인데, 번역이 조금 마음에 안들긴 하지만 책 자체는 매우 훌륭한것 같다.

먼저 Perl을 시작하기 앞서서, Linux 환경이 조금 낯선 나이기 때문에  Vim Editor를 먼저 Setting해 보앗다.


http://skyloader.tistory.com/2


skyloader님의 blog에는 3가지 plug 인을 추천해주셨는데, 아직 vim에 익숙치 않아 엄청난 파워를 느낄순 없지만

Perl 코딩을 하는데 있어서 매우 큰 도움을 줄거라 확신한다.


1. Perl omni completion Plug in

http://www.vim.org/scripts/script.php?script_id=2852


2. perl-support-vim

http://www.vim.org/scripts/script.php?script_id=556


3. textMate-style nippets for vim

http://www.vim.org/scripts/script.php?script_id=2540


.vimrc는 검색하다가 발견한 것으로 대체한다.


http://www.codedanger.com/caglar/archives/409


사용법 및 설치법은 Manual에 자세히 설명되어 있으니 생략하도록 한다.


현재 .vimrc는 아래와 같이 설정되어 있다.


"syntax highlighting

set bg=light

syntax on

 

set ruler

set number

set smarttab

set fileformats=unix,dos,mac " support all three, in this order

set formatoptions=tcqor " t=text, c=comments, q=format with "gq", o,r=autoinsert comment leader

set cindent                             " indent on cinwords

set shiftwidth=4                " set shiftwidth to 4 spaces

set tabstop=4                   " set tab to 4 spaces

set showmatch                   " Show matching brackets/braces/parantheses.

set background=dark     " set background to dark

set showcmd                             " Show (partial) command in status line.

set autowrite                   " Automatically save before commands like :next and :make

set textwidth=98                " My terminal is 98 characters wide

set visualbell                          " Silence the bell, use a flash instead

set cinoptions=:.5s,>1s,p0,t0,(0,g2     " :.5s = indent case statements 1/2 shiftwidth

set cinwords=if,else,while,do,for,switch,case,class,try   " Which keywords should indent

set showmatch

set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ [POS=%04l,%04v]\ [%p%%]\ [LEN=%L] "Shows detailed status line with formatting

set laststatus=2 "This Makes the status bar visible

set mat=5

set tabstop=2 shiftwidth=2 expandtab

filetype on

filetype plugin on

filetype indent on

set modeline

set mouse=a

set nocompatible

 

" vimrc file for following the coding standards specified in PEP 7 & 8.

"

" To use this file, source it in your own personal .vimrc file (``source

" <filename>``) or, if you don't have a .vimrc file, you can just symlink to it

" (``ln -s <this file> ~/.vimrc``).  All options are protected by autocmds

" (read below for an explanation of the command) so blind sourcing of this file

" is safe and will not affect your settings for non-Python or non-C files.

"

"

" All setting are protected by 'au' ('autocmd') statements.  Only files ending

" in .py or .pyw will trigger the Python settings while files ending in *.c or

" *.h will trigger the C settings.  This makes the file "safe" in terms of only

" adjusting settings for Python and C files.

"

" Only basic settings needed to enforce the style guidelines are set.

" Some suggested options are listed but commented out at the end of this file.

 

" Number of spaces that a pre-existing tab is equal to.

" For the amount of space used for a new tab use shiftwidth.

au BufRead,BufNewFile *py,*pyw,*.c,*.h,*.pl,*.pm,*.php set tabstop=8

 

" What to use for an indent.

" This will affect Ctrl-T and 'autoindent'.

" Python and PHP: 4 spaces

" C and perl : tabs (pre-existing files) or 4 spaces (new files)

au BufRead,BufNewFile *.py,*pyw,*.php set shiftwidth=4

au BufRead,BufNewFile *.py,*.pyw,*.php set expandtab

 

fu Select_c_style()

    if search('^\t', 'n', 150)

        set shiftwidth=8

        set noexpandtab

    el 

        set shiftwidth=4

        set expandtab

    en

endf

au BufRead,BufNewFile *.c,*.h,*.pl,*.pm,*.php call Select_c_style()

au BufRead,BufNewFile Makefile* set noexpandtab

 

" Use the below highlight group when displaying bad whitespace is desired.

highlight BadWhitespace ctermbg=red guibg=red

 

" Display tabs at the beginning of a line in Python mode as bad.

au BufRead,BufNewFile *.py,*.pyw match BadWhitespace /^\t\+/

" Make trailing whitespace be flagged as bad.

au BufRead,BufNewFile *.py,*.pyw,*.c,*.h,*.pl,*.pm,*.php match BadWhitespace /\s\+$/

 

" Wrap text after a certain number of characters

" Python: 79 

" C: 79

" Perl: 79

" PHP: 79

au BufRead,BufNewFile *.py,*.pyw,*.c,*.h,*.pl,*.pm,*.php set textwidth=79

 

" Turn off settings in 'formatoptions' relating to comment formatting.

" - c : do not automatically insert the comment leader when wrapping based on

"    'textwidth'

" - o : do not insert the comment leader when using 'o' or 'O' from command mode

" - r : do not insert the comment leader when hitting <Enter> in insert mode

" Python and Perl: not needed

" C: prevents insertion of '*' at the beginning of every line in a comment

au BufRead,BufNewFile *.c,*.h set formatoptions-=c formatoptions-=o formatoptions-=r

 

" Use UNIX (\n) line endings.

" Only used for new files so as to not force existing files to change their

" line endings.

" Python: yes

" C: yes

" Perl: yes

au BufNewFile *.py,*.pyw,*.c,*.h,*.pm,*.php set fileformat=unix

 

 

" ----------------------------------------------------------------------------

" The following section contains suggested settings.  While in no way required

" to meet coding standards, they are helpful.

 

" Set the default file encoding to UTF-8: ``set encoding=utf-8``

 

" Puts a marker at the beginning of the file to differentiate between UTF and

" UCS encoding (WARNING: can trick shells into thinking a text file is actually

" a binary file when executing the text file): ``set bomb``

 

" For full syntax highlighting:

"``let python_highlight_all=1``

"``syntax on``

 

" Automatically indent based on file type: ``filetype indent on``

" Keep indentation level from previous line: ``set autoindent``

 

" Folding based on indentation: ``set foldmethod=indent``

 

" Show tabs and trailing spaces.

" Ctrl-K >> for »

" Ctrl-K .M for ·

" (use :dig for list of digraphs)

set list listchars=tab:»»,trail:·

 

" my perl includes pod

let perl_include_pod = 1

" syntax color complex things like @{${"foo"}}

let perl_extended_vars = 1

 

" Fold the code block when <F2> is pressed

set foldmethod=marker

nmap <F2> 0v/{<CR>%zf




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

Chapter 4 & Chapter 5  (0) 2012.10.05
Posted by 박세범
Programming/C#2011. 12. 25. 02:06

The source codes seem like working only for Window OS 32bit, but 64 bit works perfectly The only problem is "privilege" That's the problem. we must run this application as an administration
       


                     ManagementBaseObject mboShutdown = null;
                    ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
                    mcWin32.Get();
                    mcWin32.Scope.Options.EnablePrivileges = true;      // get security privileges
                    ManagementBaseObject mboShutdownParams = mcWin32.GetMethodParameters("Win32Shutdown");
                    mboShutdownParams["Flags"] = "1";
                    mboShutdownParams["Reserved"] = "0";
                    foreach (ManagementObject manObj in mcWin32.GetInstances())
                    {
                        mboShutdown = manObj.InvokeMethod("Win32Shutdown", mboShutdownParams, null);
                    }
                    break;
                    



'Programming > C#' 카테고리의 다른 글

Palindromic number source  (0) 2011.10.19
Posted by 박세범
Programming/File Structure2011. 12. 23. 17:22
File Structure assignment, it works perfectly well BTree.java
import java.io.*;
import java.util.*;

// 실제로 BTree를 구현할 class

public class BTree {
	
	
	public BTreeNode rootNode;
	
	public BTree()
	{
		rootNode = new BTreeNode();
	}
	
	public boolean insert(BTreeData data) throws Exception			// 생성부분 완료
	{
		Stack stack = new Stack();		// 삽입시 참조되는 순서를 저장하게 될 stack

		BTreeNode parentNode = null; 		
		BTreeNode currentNode = rootNode;
		BTreeNode newNode = null;
		
		currentNode = rootNode;
		int i=0;
		
		//int totalCount = 
		while(currentNode != null)
		{
			parentNode = currentNode;
			stack.push(parentNode);		// Stack에 부모노드들이 차근 차근 쌓아둔다.(나중에 split or merge시 사용)
			
			for(i=0;i data.key)	// 만약 bucket의 키 값이, data key보다 클 경우
				{											// 그 의미는 곧 삽입해야할 곳을 찾았다는 의미
					break;
					
				}
			}
			currentNode = currentNode.childNode[i];		// 실제 insert 될 곳의 node는 여기 들어간다.
		}
		if(parentNode == null)	// root에 아무것도 없는 경우
		{
			rootNode.data[0] = data;
			rootNode.elementCount = 1;
		}
		else		// root노드가 비어있지 않은 경우(일반정인 경우라면)(그리고 여기선 순서대로 저장되야 한다. sort함수를 사용하자)
		{
			insertDataBTree(parentNode,data, null);
			splitNode(stack);
		}
		return true;
	}
	
	
	//실제 Data를 입력하는 함수이다.
	public void insertDataBTree(BTreeNode currentNode, BTreeData data, BTreeNode RChildNode) throws Exception
	{
		@SuppressWarnings("null")
		int elementIndex = currentNode.elementCount;
		int i=0;			// 실제로 삽입될 index
		
		for( i = elementIndex-1 ; i>=0;i--)		// 자료를  이동하는 함수
		{
			int tempKey = currentNode.data[i].key;
			
			if(tempKey> data.key)			// 한칸씩 땡기게 된다.
			{
				currentNode.data[i+1] = currentNode.data[i];
				currentNode.childNode[i+2] = currentNode.childNode[i+1];
			}
			else
				break;
		}
		
		currentNode.data[i+1] = data;					// 실제 데이터 삽입부분, i--이므로
		currentNode.childNode[i+2] = RChildNode;		// 우 노드를 삽입한다(이는 merge와 split시 필요하다)
		currentNode.elementCount++;					// 
	}
	
	public void showBTree()					// 출력 함수
	{
		if(rootNode == null)
		{
			System.out.println("There is no data!!! BTree is empty!");
		}
		else
		{
			showBTreeByRecur(rootNode);
		}
	}
	
	public void showBTreeByRecur(BTreeNode Node)			// 출력 부분
	{
		// post-order traversals.
		if(Node != null)
		{
			for(int i=0;i stack) 		// 분할 함수 부분
	{
		BTreeNode parentTreeNode = null;
		BTreeNode currentTreeNode = null;
		BTreeNode newNode = null;
		BTreeData middleElement = null;
		BTreeNode tempNode;
		int middleIndex = 5/2;
		currentTreeNode = stack.pop();		// 가장 최상위 stack의 값을 가져온다.
		while(currentTreeNode != null)
		{
			//currentTreeNode = tempNode; 
			if(currentTreeNode.elementCount >= 5)	// 만약 5보다 element가 크다면(실제로 데이터는 M-1개 즉 4개밖에 저장하지 못한다)
			{
				newNode = new BTreeNode();		
				middleElement = new BTreeData();
				middleElement = currentTreeNode.data[middleIndex];		// 중간요소를 저장한다.
				currentTreeNode.data[middleIndex] = null;			// 이 부분을 없애준다.
				
				int j =0;
				int i;
				for(i= middleIndex + 1 ; i<5; i++)		// 중간 이후의 노드들은 분할되기 위해서 다 복사된다.
				{
					newNode.data[j] = currentTreeNode.data[i];
					newNode.childNode[j] = currentTreeNode.childNode[i];
					currentTreeNode.data[i] = null;
					currentTreeNode.childNode[i] = null;
					j++;
				}
				newNode.childNode[j] = currentTreeNode.childNode[i];		// m원 트리에서 node개수는 m-1개 subTree는 m개이기 떄문에
				currentTreeNode.childNode[i] = null;						// 이 작업을 반드시 해줘야한다.
				
				newNode.elementCount = 5/2;			// 분할되면 2개만 저장하게 된다.(5개 이므로)
				currentTreeNode.elementCount = 5/2;		// 현재 노드의 element 개수도 반이 된다고 명시해준다.
				
				// 여기서부터는 상위 부모 노드를 가져온다.
				try
				{
					parentTreeNode = stack.pop();		// 부모노드 가져오기
					insertDataBTree(parentTreeNode, middleElement, newNode);
				}
				catch(Exception e)			// 더 이상 pop하지 못하면 이 예외가 발생하게 된다.
				{
					rootNode = new BTreeNode();		// root노드를 하나 새로이 다시 만들고
					rootNode.data[0] = middleElement;		// 중간값을 새로 집어 넣고
					rootNode.elementCount++;		// 전체 개수를 증가 시킨 후
					rootNode.childNode[0] = currentTreeNode;		// 왼쪽 subtree는 현재껄로
					rootNode.childNode[1] = newNode;		// 다른쪽은 새로운 걸로 삽입한다.
				}
			}
			currentTreeNode = parentTreeNode;			// 계속해서 올라가야 한다.
			parentTreeNode = null;
		}
		
	}
	
	
	public boolean removeNode(int key) throws Exception
	{	
		int i = 0; 	// counter 변수
		//int index = 0;
		boolean isFind = false;		// 만약 검색해서 해당 노드를 찾지 못할경우 이 flag가 쓰인다.
		BTreeNode parentNode = null;
		BTreeNode currentNode = null;
		Stack stack = new Stack();		// stack을 하나 생성한다(노드 분할 및 balance를 위해서 쓰인다)
		
		currentNode = rootNode;
		
		while(currentNode != null && isFind == false)			// 이부분은 insert함수와 똑같지만, 찾을 때까지 수행하는 것만 다르다.
		{
			parentNode = currentNode;
			stack.push(parentNode);		// Stack에 부모노드들이 차근 차근 쌓아둔다.(나중에 split or merge시 사용)
			
			for(i=0;i key)	// 만약 bucket의 키 값이, data key보다 클 경우
				{											// 그 의미는 곧 삽입해야할 곳을 찾았다는 의미
					break;
				}
			}
			currentNode = currentNode.childNode[i];		// 실제 insert 될 곳의 node는 여기 들어간다.
		}
		
		if(isFind == true)		// 만약 원하는 키를 찾았다면
		{
								// 먼저 leaf node가 잇는지 검사한다.
			if(parentNode.childNode[0] == null)		// 현재노드가 아무것도 가리키지 않을 경우
			{
				deleteKeyBTree(parentNode, i);
				// deleteKeyBt 를 수행하는 부분
			}
			else			// leaf 노드가 잇다면
			{
				parentNode = replaceLeafNodeBTree(parentNode, i, stack);		// leaf 노드의 맨 끝 부분을 끌어 당기는 함수
				// replaceLeafNodebt를 수행한다.
			}			
			if(parentNode.elementCount < 5/2)		// 만약 최소 개수보다 작다면
			{
				balanceBTree(stack);
				//
			}
			return true;
			
		}
		else
		{
			System.out.println("The Key cannot be found! Try this again");
			return false;
		}
	}
	
	public void balanceBTree(Stack stack) throws Exception
	{
		BTreeNode parentNode = null;
		BTreeNode currentNode = null;
		BTreeNode newNode = null;
		BTreeNode leftNode = null;
		BTreeNode rightNode = null;
		
		BTreeData pivotData = new BTreeData();		// stack 가장 윗부분에 있는 node
		int index = 0;			// parentNode로부터 currentNode의 위치를 받을 변수
		int i= 0;
		
		currentNode = stack.pop();
		
		if(currentNode.elementCount >= 5/2)			// 만약 balance 유지할 필요가 없다면(1/2보다 크다)
			return;
		
		try
		{
			parentNode = stack.pop();					// 2번째 stack을 받는다(부모 노드)
		}
		catch(Exception e)			// 만약 부모노드에 아무것도 없다면 return한다.
		{
			return;
		}
		
		for(int j=0;i= ((5/2) + 1)))
		{
			borrowRightNodeBTree(parentNode,currentNode,index,parentNode.childNode[index+1]);
		}
		else if(index > 0 && (parentNode.childNode[index-1].elementCount >= ((5/2) + 1)))		// 왼쪼깅 다 많다면
		{
			// 여기는 왼쪽에서 빌린다.
			borrowLeftNodeBTree(parentNode,currentNode,index,parentNode.childNode[index+1]);
		}
		else		// 그렇지 않으면 merge한다.
		{
			mergeNodeBTree(stack,parentNode,currentNode,index);
		}
		
	}
	
	public void mergeNodeBTree(Stack stack, BTreeNode parentNode, BTreeNode currentNode, int index) throws Exception
	{
		BTreeNode leftNode = null;
		BTreeNode rightNode = null;
		BTreeData parentData = new BTreeData();
		BTreeNode parentParentNode = null;		//조상 노드.
		
		int i=0;
		int pivotIndex = 0;
		// 예외 처리 생략
		
		// 오른쪽으로 병합하는 경우
		if(index< parentNode.elementCount)
		{
			leftNode = currentNode;			// 현재노드가 left node가 되고
			rightNode = parentNode.childNode[index+1];	// 오른쪽 node는 parent의 오른쪽이 되고
			pivotIndex = index;				// pivot은 현재 index가 되고
			parentData = parentNode.data[pivotIndex];	// 그 데이터는 원래 index가 되고
		}
		else		// 왼쪽으로 합병하는 경우
		{
			leftNode = parentNode.childNode[index-1];
			rightNode  = currentNode;
			pivotIndex = index - 1;
			parentData = parentNode.data[pivotIndex];
		}
		insertDataBTree(leftNode, parentData, rightNode.childNode[0]);	// 0번째 요소에 왼쪽 data를 넣는다. 왼쪽에 parent 자료 추가
		
		for(i=0;i stack)
	{
		BTreeNode returnNode = null;
		BTreeData leafNodeData = new BTreeData();
		BTreeNode childNode = null;
		BTreeNode parentNode = deleteNode;
		int elementCount = index;
		do		// stack에 하나하나 다 쌓아둔다(나중에 balance를 유지할 때 필요하다)
		{
			childNode = parentNode.childNode[elementCount];		// parentNode의 삭제될 부분 뒤부터
			stack.push(childNode);		// 하나하나 씩 stack에 쌓아 논다.
			
			elementCount = childNode.elementCount;		// elementCount는 새로운 childNode의 elementCount가 되고 
			parentNode = childNode;		// 반복하여 수행한다.
			
		}while(childNode.childNode[elementCount] != null);
		
		leafNodeData = childNode.data[childNode.elementCount-1];		// 가장 오른쪽 끝에 있는걸 가져오고
		deleteNode.data[index] = leafNodeData;				// 삭제할 노드의 끝부분에다가 왼쪽끝의 요소를 대체한다.
		deleteKeyBTree(deleteNode, elementCount-1);			// 그리고 그 삭제될 바로 앞에 있는 요소를 삭제한다(원래 우리가 삭제하길 원했던 부분이다)
		returnNode = childNode;
		
		return returnNode;
	}
	
	
	public void deleteKeyBTree(BTreeNode parentNode, int index)		// 삭제 후 요소들을 한칸 씩 당기는 함수
	{
		int i=0;
		if(parentNode != null)
		{
			for(i = index + 1; i < parentNode.elementCount; i++)		// 앞으로 한칸 씩 떙긴다
			{
				parentNode.data[i-1] = parentNode.data[i];
				parentNode.childNode[i] = parentNode.childNode[i+1];
			}
			parentNode.data[parentNode.elementCount - 1] = null;		// 요소를 하나 삭제하고
			parentNode.childNode[parentNode.elementCount] = null;		// 역시 끝에 포인터도 null로 만든다.
			parentNode.elementCount--;									// 전체 요소의 개수를 줄이고
			
		}
		
	}
}


BTreeData.java

import java.io.*;

public class BTreeData 		// 데이터 부분
{
	public int key;
	public Object value; 
	BTreeData(int _key, Object _value)		// 2개의 부분으로 overloading 되어 있다.
	{
		key = _key;
		value = _value;
	}
	BTreeData()
	{
		key=0;
		value = null;
	}
}



BTreeNode.java

import java.io.*;



public class BTreeNode
{
	public BTreeNode childNode[];
	public BTreeData data[];
	public int elementCount;				// 총 Element Count가 있다.
	
	BTreeNode()
	{
		childNode = new BTreeNode[6];		// M-5 트리, 추가로 하나의 여유분을 둔다.. 우선 insert한후에 split하기 위해서
		data = new BTreeData[5];			
	}
	public void setData(int index, BTreeData TreeData)
	{
		data[index] = TreeData;
		
	}
}

mainFunction.java

import java.io.Console;
import java.util.Scanner;


public class mainFunction {

	public static void main(String args[]) throws Exception
	{
		BTree bt = new BTree();					// B-Tree 생성
		Scanner scan = new Scanner(System.in);	// Scanner 생성
		System.out.println("Welcome to B-Tree's world!!!!!");		
		int input=0;
		do
		{
			System.out.println("\n1. Input Data");				// Menu 출력
			System.out.println("2. Remove Data with Key value");
			System.out.println("3. Show B-Tree by post-order traversal method");
			System.out.println("Please Enter the menu number(Exit is 0)\n");	
			
			String temp = scan.nextLine();				// 입력받기
			try
			{
				input = Integer.valueOf((temp));		// switch 문을 위해서 변환을 해준다.
			}
			catch(Exception e)							// 예외 처리
			{
				System.out.println("Please enter the correct number please");
				continue;
			}
			
			switch(input)								
			{
			case 1:										// 1번은 insert function
				String temp1 = new String();
				String temp2 = new String();
				System.out.println("Please Enter the Key number");
				temp1 = scan.nextLine();
				System.out.println("Please Enter the Any String Data you want");
				temp2 = scan.nextLine();
				BTreeData tmpData = new BTreeData(Integer.valueOf(temp1),temp2);		// 입력받은 값을 가지고 data를 생성한다.
				if(bt.insert(tmpData))
					System.out.println("Successful!");
				else
					System.out.println("Failed");
				break;
			case 2:										// 2번은 remove function
				String tempRemoveKey = new String();
				System.out.println("Please Enter the key you want to remove from B-Tree");
				tempRemoveKey = scan.nextLine();
				if(bt.removeNode(Integer.valueOf(tempRemoveKey)))			// 삭제한다.
					System.out.println("Successful!");
				else
					System.out.println("Failed");
				break;
			case 3:						// 3번은 출력 
				System.out.println("\nThe B-Tree will be shown soon\n");
				bt.showBTree();				// 출력한다.
				break;
			case 0:						// 0은 프로그램 종료
				System.out.println("The program will be terminated");
				break;
			default:
				System.out.println("Please Enter correct number");
				break;
			}
		}while(input!=0);
		

	}
}


/*
BTreeData b1 = new BTreeData(69, "b1");			BTreeData b2 = new BTreeData(7, "b2");
BTreeData b3 = new BTreeData(150, "b3");		BTreeData b4 = new BTreeData(19, "b4");
BTreeData b5 = new BTreeData(70, "b5");		BTreeData b6 = new BTreeData(20, "b6");
BTreeData b7 = new BTreeData(128, "b7");		BTreeData b8 = new BTreeData(18, "b8");
BTreeData b9 = new BTreeData(42, "b9");		BTreeData b10 = new BTreeData(120, "b10");
BTreeData b11 = new BTreeData(140, "b11");		BTreeData b12 = new BTreeData(16, "b12");
BTreeData b13 = new BTreeData(100, "b13");		BTreeData b14 = new BTreeData(26, "b14");
BTreeData b15 = new BTreeData(145, "b15");		BTreeData b16 = new BTreeData(15, "b16");
BTreeData b17 = new BTreeData(110, "b17");		BTreeData b18 = new BTreeData(30, "b18");
BTreeData b19 = new BTreeData(40, "b19");		BTreeData b20 = new BTreeData(132, "b20");
BTreeData b21 = new BTreeData(138, "b21");		BTreeData b22 = new BTreeData(50, "b22");
BTreeData b23 = new BTreeData(43, "b23");		BTreeData b24 = new BTreeData(130, "b24");
BTreeData b25 = new BTreeData(136, "b25");		BTreeData b26 = new BTreeData(41, "b26");
BTreeData b27 = new BTreeData(59, "b27");		BTreeData b28 = new BTreeData(54, "b28");
BTreeData b29 = new BTreeData(122, "b29");		BTreeData b30 = new BTreeData(124, "b3o");


bt.insert(b1);		bt.insert(b2);		bt.insert(b3);		bt.insert(b4);	
bt.insert(b5);		bt.insert(b6);		bt.insert(b7);		bt.insert(b8);		
bt.insert(b9);		bt.insert(b10);		bt.insert(b11);		bt.insert(b12);		
bt.insert(b13);		bt.insert(b14);		bt.insert(b15);		bt.insert(b16);		
bt.insert(b17);		bt.insert(b18);		bt.insert(b19);		bt.insert(b20);
bt.insert(b21);		bt.insert(b22);		bt.insert(b23);		bt.insert(b24);	
bt.insert(b25);		bt.insert(b26);		bt.insert(b27);		bt.insert(b28);		
bt.insert(b29);		bt.insert(b30);

System.out.println("All datas have been inserted, it will be shown by post-order traversal");

bt.showBTree();		

System.out.println("Removing data........");


bt.removeNode(138);		bt.removeNode(50);		bt.removeNode(43);
bt.removeNode(130);		bt.removeNode(136);		bt.removeNode(41);
bt.removeNode(59);		bt.removeNode(54);		bt.removeNode(122);
bt.removeNode(124);

System.out.println("Removing task has been completed, now printing B-Tree");

bt.showBTree();		
*/


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

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