2012년 2월자 기준

1위 - JAVA
2위 - C
3위 - C#
4위 - C++
5위 - Objective-C
6위 - PHP
7위 - Visual Basic
8위 - Python
9위 - Perl
10위 -  Java script

'Notes > Tech History' 카테고리의 다른 글

command line에서 폴더 삭제  (0) 2015.03.20
zip 명령어  (0) 2015.03.20
파일 입출력, 파일 포인터(FILE* fp)  (0) 2012.01.02
싱글턴 클래스  (0) 2011.10.17
OpenAL의 시작  (3) 2010.12.02
헤더파일 : StoreKit/StoreKit.h
라이브러리파일 : StoreKit.framework
딜리게이트 : SKProductsRequestDelegate

상품 요청
SKProductsRequest *preq = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:PRODUCT_ID]];
preq.delegate = self;
[preq start]; 
 - PRODUCT_ID : In app purchase에 등록한 상품 아이디를 입력하시면 됩니다.
ex)com.sadun.app.item1

상품 요청에 대한 응답
-(void)productsRequest(SKProductsRequest*)req didReceiveResponse:(SKProductsResponse*)response
{
    if([response.products count] >0)
    {
        for( SKProduct* product in response.products )
        {
            SKPayment *pPayment = [SKPayment paymentWithProduct:product];

            NSLog(@"Title:%@", product.localizedTitle);
            NSLog(@"Description:%@", product.localizedDescription);
            NSLog(@"Price:%@", product.price);

            [[SKPaymentQueue defaultQueue] addPayment:pPaymen];
        }
    }
    if([response.invalidProductIdentifiers count] > 0)
    {
        printf("find invalid product\n");
        for(NSString* invalidString in [response invalidProductIdentifiers])
        {
            NSLog(@"Invalid Identifiers:%@", invalidString);
        }
    }
    [req autorelease];
}

결제 후 처리
-(void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transactions
{
    for( SKPaymentTransaction* tran in transactions )
    {
        switch( tran.transactionState )
        {
            case SKPaymentTransactionStatePurchasing:
                /*----------------------------------------
                구매 중 처리
                ----------------------------------------*/
                break;
            case SKPaymentTransactionStatePurchased:
                /*----------------------------------------
                구매 후 처리
                ----------------------------------------*/
                break; 
            case SKPaymentTransactionStateRestored:
                /*----------------------------------------
                이미 구매 됨 처리
                ----------------------------------------*/
                break; 
            case SKPaymentTransactionStateFailed:
                /*----------------------------------------
                구매 실패 처리
                ----------------------------------------*/
                break;
            default:
                break;
        }
    }
}


아이폰은 잠겨져있는 것들이 많다.
사용자들에게는 상관없는것들은 다 접근이 힘들다.

resource폴더
 - resource폴더는 어플리케이션에 쓰일 리소스들이 있는 폴더다. 프로그래머는 이곳에 리소스들을 넣어놓고 접근을하여 사용한다.
 - 읽기만 가능.
 - 접근방법
NSString* resourceDir = [[NSBundle mainBundle] resourcePath];
const char* szResourceDir = [resourceDir UTF8String];

document폴더
 -  document폴더는 어플리케이션에 필요한 데이터들이 있는 폴더다. 프로그래머는 이곳에서 필요한 데이터를 저장하고 불러와 사용할 수 있다.
 - 읽고, 쓰는것 가능.
 - 접근방법
NSArray* pMyPathList = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
NSString* pMyPath = [pMyPathList objectAtIndex:0];
const char* szResourceDir = [pMyPath UTF8String];

그 다음엔 string함수들을 이용해서 알아서 쓰면된다.
파일포인터는 쓸때마다 까먹는것 같습니다.
사용하는 함수들도 많고... fopen할때도 옵션은 또 뭐 그리 많은지

파일포인터란
파일을 가르키는 포인터입니다.

FILE* fp = fopen("FileName.txt", "rb");
FILE* - 파일포인터 입니다. 
fopen -  파일을 불러오는 함수입니다.
"FileName.txt" -  파일 이름입니다.
"rb" - 파일을 불러올때의 옵션입니다.
 
파일 옵션
r
- 읽기 전용, 파일이 존재하지 않을 경우 NULL을 리턴.
w
- 쓰기 전용, 파일이 존재하지 않을 경우 새로 만들고, 파일이 존재할 경우 삭제하고 새로 만든다.
a
- append(덧붙이다), 파일이 존재하지 않을 경우 새로 만들고, 파일이 존재할 경우 파일 맨 끝에 파일포인터가 존재하게 된다. 맨 끝에서부터 쓰기가능.

r+ -  읽기, 쓰기 - 파일이 존재하지 않을 경우 NULL을 리턴.
w+ - 읽기, 쓰기 - 파일이 존재하지 않을 경우 새로 만들고, 파일이 존재할 경우 삭제하고 새로 만든다.
a+ - append(덧붙이다.),   파일이 존재하지 않을 경우 새로 만들고, 파일이 존재할 경우 파일의 맽 끝에 파일포인터가 존재하게 된다. 읽기는 fseek로 지정한 file pointer위치에서 가능하나 쓰기는 파일 끝부분에서만 가능.

b - 바이너리형식
t - 텍스트형식 

'Notes > Tech History' 카테고리의 다른 글

zip 명령어  (0) 2015.03.20
프로그래밍 언어 순위  (0) 2012.02.02
싱글턴 클래스  (0) 2011.10.17
OpenAL의 시작  (3) 2010.12.02
TCP기반의 에코서버/클라이언트  (0) 2010.08.19

GCC C++ Link problems on small embedded target

Thought someone might be interested in this...

I spent Thursday night and Friday night investigating some link errors I was getting on my robot project, which is small embedded ARM7 target compiling C++ code under GCC.

So here is the detail of the errors:

speed_control.o: In function `~Speed_Control':
source/speed_control.cpp:35: undefined reference to `operator delete(void*)'
speed_control.o: In function `~Sensing_Callback':
source/motor_sensing.h:38: undefined reference to `operator delete(void*)'
speed_control.o:(.rodata._ZTI13Speed_Control[typeinfo for Speed_Control]+0x0): undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
speed_control.o:(.rodata._ZTI16Sensing_Callback[typeinfo for Sensing_Callback]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
speed_control.o:(.rodata._ZTV16Sensing_Callback[vtable for Sensing_Callback]+0x8): undefined reference to `__cxa_pure_virtual'


All of these problems were caused by the fact that I'm not using the C++ libraries - either the compiler C++ support libraries or the standard libraries. And the very summarized version is that none of them were particularly hard to overcome - once you knew why they were happening! This post is about what they are.

Why aren't I using the standard stuff? This is because I don't have much flash or RAM. Well, actually I have 128K of Flash (which I expect I won't use up) and 60K of RAM (which I'm going use a significant fraction for a large data store ... all will be revealed in a later blog entry). It's quite common for embedded systems to roll their own nearly everything. I do link against certain libraries. But certainly nothing like heap management, cout or printf.

Undefined References to class_type_info

Starting with with the undefined references to
`vtable for __cxxabiv1::__vmi_class_type_info'
and
`vtable for __cxxabiv1::__class_type_info'
- these are related to RTTI (run-time type information) as suspected, and are functions patched into the RTTI table. There is a pointer to this from the vtable.

This is the vtable:

507 _ZTV16Sensing_Callback:
508 0000 00000000 .word 0
509 0004 00000000 .word _ZTI16Sensing_Callback
510 0008 00000000 .word __cxa_pure_virtual
511 000c 00000000 .word _ZN16Sensing_CallbackD1Ev
512 0010 00000000 .word _ZN16Sensing_CallbackD0Ev


As you can see, address 4 points at the type table.

492 _ZTI16Sensing_Callback:
493 0000 08000000 .word _ZTVN10__cxxabiv117__class_type_infoE+8
494 0004 00000000 .word _ZTS16Sensing_Callback


Obviously those are mangled names ... and I've left off a whole other block - this is the pure abstract base class, effectively an interface, part of a concrete class.

Since I'm not using rtti at all, we can get rid of this by adding "-fno-rtti" to the gcc command line options. Both errors go away.


Undefined Reference to `__cxa_pure_virtual'

This one is interesting. Effectively it's a function that is called if you actually (somehow) call apure virtual member function. Remember that you don't give them a definition (by putting =0) in the class after the member function definition. As you know - this does two things, forces you to define it in any derived classes and stop you making a concrete version of that base class.

I guess you've have to be hacking the vtable or doing some very bizarre casting to get this at all without the compiler spotting it. Either way, I think it's part of the language standard I think - I believe gcc's standard lib does an abort.

eCos has some information on it, as does the OS Dev Wiki.

http://sourceware.org/ml/ecos-patches/2003-03/msg00209.html

http://www.osdev.org/wiki/C_PlusPlus

We just sit in a loop, because I think it will never happen to us.

extern "C" void __cxa_pure_virtual(void)
{
// call to a pure virtual function happened ... wow, should never happen ... stop
while(1)
;
}



Undefined Reference to operator delete(void *)

The final ones quite good ... and Google really didn't help direct me to the information in any sort of quick way.

So, I don't use new and delete - because we haven't got a heap, and the memory on the single-chip microcontroller is not really large enough to use that type memory management (certainly not with my usage). It's all stack based and static objects for us. But that's ok.

So why is gcc generating a delete? Turns out there is more than one destructor in gcc (and there also can be two types of constructor as well - but I'll just cover destructors here). If the destructors are virtual they will appear in the vtable (there are two in the vtable one above - but another class has three). How gcc decides to generate 2 or 3, I haven't found out.

In summary, these three are:
  • in-charge deleting (the destructor also deletes the memory space) ... has D0Ev at the end of the mangled name.
  • in-charge (the destructor is allowed call other destructors) ... has D1Ev at the end of the mangled name.
  • not-in-charge (the destructor is NOT allowed to call other destructors ... and this has D2Ev at the end of the mangled name.
(v means void (i.e. no parameters) by the way).

So why the difference between in-charge and not-in-charge? Well, it's got to do with virtual inheritance (as opposed to virtual member functions). The summarised version is that these are multiple inherited classes that have a single base class at some point where we want one object copy rather than a copy for each derived path.

The rules say, to avoid trying to 'destruct' these common base classes multiple times, that only the most-derived class can sort out calling the destructors (and this is probably the simplest method, anyhow).

Also note that multiple destructors is not the only way of handling this ... earlier versions of gcc passed parameters into the destructor and generated code to select the desired operation. However, you get this speed overhead all the time. Extra entries removes this problem - because you can call the one you want directly.

The 'in-charge deleting' version is, I'm guessing, when you destroy an object by calling delete on it. Therefore gcc only needs to arrange to call the destructor. Of course this will always be "in-charge", since it's likely to be at the top of a hierarchy ("most-derived").

Some more information for this topic, mainly about virtual inheritance:

The OS Dev Wiki touches on the solution: http://www.osdev.org/wiki/C_PlusPlus

This GNU list describes the virtual inheritance stuff, what's called when:http://lists.gnu.org/archive/html/bug-gnu-utils/2004-07/msg00042.html

Notes about the implementation: http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00403.html

Actual details of what's called when from the closed items of a bug tracking system. Search for C-5 and C-6 - there are quite a few more details. C-4 is interesting as well.http://www.codesourcery.com/cxx-abi/cxx-closed.html

My actual solution? Added this to my project...


void operator delete(void *)
{
// should never get here ... we don't use new
while(1)
;
}

 
template<class S>
class Sington
{
private:
S();
S(S&);
~S(); 
S& operator=(S&) const;
static S* pMe; 
public:
static S* getMe(){return pMe;}
static void init(){pMe = new S(); pMe = NULL;}
static void release(){if(pMe != NULL)delete pMe;} 
}; 


'Notes > Tech History' 카테고리의 다른 글

프로그래밍 언어 순위  (0) 2012.02.02
파일 입출력, 파일 포인터(FILE* fp)  (0) 2012.01.02
OpenAL의 시작  (3) 2010.12.02
TCP기반의 에코서버/클라이언트  (0) 2010.08.19
리눅스 기본 명령어  (1) 2010.08.17

Openal에 대한 정보가 너무 없네요... 특히 한국어로 된 정보는 찾기 너무 힘듬..ㅜ;;
어떻게 제가 찾은 정보라도 번역해서 포스트 해봅니다.
 
 
1. Opanal 구조

OPENAL이 초기화 될 때, 적어도 하나의 Device가 초기화 되야 하고, Device하나가 초기화 될 때, 적어도 하나의 Context가 초기화 되어야 합니다. 그리고 Context가 초기화 될 때, 하나의 Listener 객체가 생성되고, 여러개의 Source객체를 생성할 수 있게 되고, 그것에 하나 또는 추가적인 Buffer객체를 연결할 수 있습니다. 여기서 Buffer는 Context의 일부가 아니라 하나의 Device에 있는 모든 Context에 섞여 나뉘어져 있는 것입니다.



2. Device 초기화

// 초기화
Device = alcOpenDevice(NULL); // 운영체제에서 사용하고 있는 오디오 장치를 사용
if (Device)
{
    Context=alcCreateContext(Device,NULL);
    alcMakeContextCurrent(Context);
}
// Check for EAX 2.0 support
g_bEAX = alIsExtensionPresent("EAX2.0");
// Buffer객체 생성
alGetError(); // error code를 비움
alGenBuffers(NUM_BUFFERS, g_Buffers);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alGenBuffers :", error);
    return;
}
// test.wav 불러옴
loadWAVFile("test.wav",&format,&data,&size,&freq,&loop);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alutLoadWAVFile test.wav : ", error);
    alDeleteBuffers(NUM_BUFFERS, g_Buffers);
    return;
}
// test.wav 데이터를 AL Buffer 0로 복사함
alBufferData(g_Buffers[0],format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alBufferData buffer 0 : ", error);
    alDeleteBuffers(NUM_BUFFERS, g_Buffers);
    return;
}
// test.wav 내보냄
unloadWAV(format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alutUnloadWAV : ", error);
    alDeleteBuffers(NUM_BUFFERS, g_Buffers);
    return;
}
// Source객체 생성
alGenSources(1,source);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alGenSources 1 : ", error);
    return;
}
// buffer 0과 source를 연결
alSourcei(source[0], AL_BUFFER, g_Buffers[0]);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alSourcei AL_BUFFER 0 : ", error);
}
// 나가기
Context=alcGetCurrentContext();
Device=alcGetContextsDevice(Context);
alcMakeContextCurrent(NULL);
alcDestroyContext(Context);
alcCloseDevice(Device);



3. Listener 속성

ALfloat listenerPos[]={0.0,0.0,0.0};
ALfloat listenerVel[]={0.0,0.0,0.0};
ALfloat listenerOri[]={0.0,0.0,-1.0, 0.0,1.0,0.0};
// Listener의 좌표...
alListenerfv(AL_POSITION,listenerPos);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alListenerfv POSITION : ", error);
    return;
}
// Listener의  속력...
// velocity is essentially the speed of sound
alListenerfv(AL_VELOCITY,listenerVel);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alListenerfv VELOCITY : ", error);
    return;
}
// Listen의 방위...
//orientation expressed as “at” and “up” vectors
alListenerfv(AL_ORIENTATION,listenerOri);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alListenerfv ORIENTATION : ", error);
    return;
}

 속성  데이터 타입  설명
 AL_GAIN  f, fv  “master gain(patch volume)”
 소리의 크기를 설정한다.
 값은 정수여야 한다.
 AL_POSITION  fv, 3f, iv, 3i  X, Y, Z 좌표
 AL_VELOCITY  fv, 3f, iv, 3i  속도 벡터
 AL_ORIENTATION  fv, iv  orientation은 at벡터와up벡터를 표현한다.




4. Buffer의 속성

// Buffer의 주파수를 재 설정함.
alBufferi(g_Buffers[0], AL_FREQUENCY, iFreq);


 속성  데이터 타입  설명
 AL_ FREQUENCY  i, iv  버퍼의 주파수(단위 Hz)
 AL_ BITS  i, iv  버퍼의 깊이(bit)
 AL_ CHANNELS  i, iv  버퍼의 채널 갯수
> 1개가 유효하지만 버퍼가 재생될 때, 설정할 수 없습니다.
 AL_ SIZE  i, iv  버퍼의 사이즈(bytes)
 AL_DATA  i, iv  original location where data was copied from
generally useless, as was probably freed after buffer creation



5. Source의 속성

alGetError(); // 에러버퍼를 비움
alSourcef(source[0],AL_PITCH,1.0f);
if ((error = alGetError()) != AL_NO_ERROR)
    DisplayALError("alSourcef 0 AL_PITCH : \n", error);
alGetError(); // 에러버퍼를 비움
alSourcef(source[0],AL_GAIN,1.0f);
if ((error = alGetError()) != AL_NO_ERROR)
    DisplayALError("alSourcef 0 AL_GAIN : \n", error);
alGetError(); // 에러버퍼를 비움
alSourcefv(source[0],AL_POSITION,source0Pos);
if ((error = alGetError()) != AL_NO_ERROR)
    DisplayALError("alSourcefv 0 AL_POSITION : \n", error);
alGetError(); // 에러버퍼를 비움
alSourcefv(source[0],AL_VELOCITY,source0Vel);
if ((error = alGetError()) != AL_NO_ERROR)
    DisplayALError("alSourcefv 0 AL_VELOCITY : \n", error);
alGetError(); // 에러버퍼를 비움
alSourcei(source[0],AL_LOOPING,AL_FALSE);
if ((error = alGetError()) != AL_NO_ERROR)
    DisplayALError("alSourcei 0 AL_LOOPING true: \n", error);

 Property  Data Type  Description
 AL_PITCH  f, fv  pitch를 설정
 정수를 입력해야 한다.
 AL_GAIN  f, fv  source의 볼륨 설정
 정수만 입력해야 한다.
 AL_MAX_DISTANCE  f, fv, i, iv  소리가 들리는 범위의 최대 거리를 설정.
 AL_ROLLOFF_FACTOR  f, fv, i, iv  the rolloff rate for the source
기본값이 1.0
 AL_REFERENCE_DISTANCE  f, fv, i, iv  the distance under which the volume for the source would normally drop by half (before being influenced by rolloff factor or AL_MAX_DISTANCE)
 AL_MIN_GAIN  f, fv  이 source의 최소 볼륨을 설정
 AL_MAX_GAIN  f, fv  이 source의 최대 볼륨을 설정
 AL_CONE_OUTER_GAIN  f, fv  the gain when outside the oriented cone
 AL_CONE_INNER_ANGLE  f, fv, i, iv  the gain when inside the oriented cone
 AL_CONE_OUTER_ANGLE  f, fv, i, iv  outer angle of the sound cone, in degrees
기본값이 360
 AL_POSITION  fv, 3f  X, Y, Z 좌표
 AL_VELOCITY  fv, 3f  속도 벡터
 AL_DIRECTION  fv, 3f, iv, 3i  방향 벡터
 AL_SOURCE_RELATIVE  i, iv  determines if the positions are relative to the listener
기본값이 AL_FALSE
 AL_SOURCE_TYPE  i, iv  source 타입– AL_UNDETERMINED, AL_STATIC, 또는AL_STREAMING
 AL_LOOPING  i, iv  반복을 on (AL_TRUE) 또는 off (AL_FALSE)로 바꾼다.
 AL_BUFFER  i, iv  the ID of the attached buffer
 AL_SOURCE_STATE  i, iv  source의 속성
(AL_STOPPED, AL_PLAYING, …)
 AL_BUFFERS_QUEUED  i, iv  the number of buffers queued on this source
 AL_BUFFERS_PROCESSED  i, iv  the number of buffers in the queue that have been processed
 AL_SEC_OFFSET  f, fv, i, iv  초(second) 단위로 플레이 위치를
 AL_SAMPLE_OFFSET  f, fv, i, iv  셈플(samples) 단위로 플레이 위치를 바꾼다.
 AL_BYTE_OFFSET  f, fv, i, iv  바이트(Bytes) 단위로 플레이 위치를 바꾼다.

 

 6. 에러 핸들링

alGetError(); // Error코드를 비움
// 버퍼를 생성
alGenBuffers(NUM_BUFFERS, g_Buffers);
if ((error = alGetError()) != AL_NO_ERROR)
{
    DisplayALError("alGenBuffers :", error);
    exit(-1);
}
 Error Code  Description
 AL_NO_ERROR  에러가 발생하지 않았음.
AL_INVALID_NAME  OpenAL 함수에 잘못된 이름이(ID) 전달됨.
 AL_INVALID_ENUM  OepanAL 함수에 잘못된 enum값이 전달됨.
 AL_INVALID_VALUE  OpenAL 함수에 잘못된 매개변수를 전달됨.
 AL_INVALID_OPERATION  요청한 작업이 유효하지 않음.
 AL_OUT_OF_MEMORY  요청한 작업에 대해 사용할 메모리가 부족할 때,

OSI 7계층

응용 계층(Application Layer)
 - 응용 프로세스를 네트워크에 연결할 수 있게 해서 자료를 송수신할 수 있는 창구를 제공한다. 사용자가 이메일을 전송하거나 웹 브라우저를 통해 웹 서버에 연결하면 해당 서비스는 응용 계층에서 SMTP, POP3 HTTP등의 프로토콜을 이용해 서비스한다.

표현 계층(Presentation Layer)
 - 통신하는 컴퓨터 간의 데이터 표현의 차이를 해결하기 위해 자료의 형식을 변환해 주거나 공통의 형식을 제공해 주는 계층이다. 아스키 코드와 EBCDIC 코드의 변환, 그래픽 정보나 영상 정보를 JPEG나 MPEG 등으로 변환해서 전송하는 기능을 수행한다. 또한 네트워크 보안을 위해 자료를 암호화해서 전송하고 수신측에서는 이를 해독하는 기능도 수행한다. 효율적으로 전송하기 위해 자료를 압축하고 압축을 푸는 기능도 수행한다.

세션 계층(Session Layer)
 - 응용 계층 사이에 연결을 설정하고, 유지하고, 종료하는 기능을 수행한다. 이를 위해 전송 계층으로 전송할 자료의 순서를 결정하고, 자료의 점검이나 복구를 위해 동기 위치(Synchronization Point) 등을 지정한다.

전송 계층(Transport Layer)
 - 통신하는 컴퓨터 간에 자료를 전송하는 계층이다. 송신측에서는 전송할 데이터를 패킷으로 분할한다. 수신측에서는 분할된 패킷을 다시 조합해서 본래의 자료로 만들고 상위 계층으로 전달한다. 수신측에서는 분할된 패킷을 다시 조합해서 본래의 자료로 만들고 상위 계층으로 전달한다. 자료가 수신측에 올바르게 전송될 수 있도록 보장하는 기능도 수행한다.

네트워크 계층(Network Layer)
 - 라우팅 프로토콜을 이용해서 최적의 전송 경로를 선택하고 이를 통해 자료를 전송하도록 한다. 이를 위해 IP 주소와 같은 논리 주소 체계와, 지리적으로 떨어져 있는 네트워크상의 두 컴퓨터 사이에 최종 목적지까지 전송하기 위해 인접한 컴퓨터까지 자료를 안전하게 전송한다.

데이터 링크 계층(Data Link Layer)
 - 물리적인 전송 링크를 통해 자료를 안전하게 전송하는 계층이다. 전송 자료의 비트들을 프레임이라는 논리 단위로 구성해서 최종 목적지까지 전송하기 위해 인접한 컴퓨터까지 자료를 안전하게 전송한다.

물리 계층(Physical Layer)
 - 컴퓨터를 서로 연결하는 물리적은 링크의 활성화/비활성화, 링크 상태를 유지하기 위해 물리적인 링크의 전기적, 기계적, 규약적, 기능적 명세를 정의한다.




TCP/IP 4계층


응용 계층(Application Layer)
 - 응용 계층은  OSI 7계층에서 세션 계층, 표현계층, 응용계층에 해당한다. 텔넷, FTP, SMTP등과 같은 TCP와 UDP 기반의 응용 프로그램을 구현할 때 사용한다.

전송 계층(Transport Layer)
 - 전송 계층은 OSI 7계층에서 전송계층에 해당한다. 통신 노드 간의 연결을 제어하고, 자료의 송수신을 담당한다. 프로토콜로는 스트림(Stream) 형태의 연결형 서비스인 TCP와 데이터그램(Datagram)형태의 비연결형 서비스인 UDP가 있다.

인터넷 계층(Internet Layer)
 - 인터넷 계층은 OSI 7계층에서 네트워크 계층에 해당한다. 통신 노드간의 IP패킷을 전송하는 기능과 라우팅 기능을 담당한다. 프로토콜로는 IP, ICMP, ARP, RARP가 있다. IP는 데이터그램 방식의 비연결형 서비스만을 제공한다.

네트워크 액세스 계층(Network Access Layer)
 - 네트워크 액세스 계층은 OSI 7계층에서 물리 계층과 데이터링크계층에 해당한다. LAN, X25, 패킷망, 위성 통신, 다이얼업 모뎀 등에 사용된다. 특히 이더넷에서는 CSMA/CD MAC 프로토콜을 사용하며 IEEE 802.3 MAC 표준으로 규정되어 있다.




//TCP기반의 에코서버
//made by chessire

#include<iostream>
#include<winsock2.h>

#pragma comment(lib, "ws2_32.lib")

void Error(char* szMessage);

void main()
{
 SOCKET s;     // 서버 소켓 디스크립터
 SOCKET cs;
 SOCKADDR_IN server;   // 소켓 구조체
 SOCKADDR_IN client;   // 소켓 구조체
 WSADATA wsaData;   // 스타트업 구조체

 int size = sizeof(client);
 char value[256];   //수신을 위한 정수값

 WSAStartup(MAKEWORD(2,2), &wsaData);

 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //TCP기반의 서버 생성(IPv4)

 if( s == INVALID_SOCKET )
 {
  Error("socket");
  return;
 }

 server.sin_family = AF_INET;     // AF_INET 체계임을 명시
 server.sin_port = htons(10000);     // 10000번 포트를 사용
 server.sin_addr.S_un.S_addr = htonl(ADDR_ANY); // 자동 네트워크 카드 설정

 if(bind(s, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
 {
  closesocket(s);
  Error("bind");
  return;
 }

 if( listen(s,SOMAXCONN) != 0 )
 {
  closesocket(s);
  Error("listen");
  return;
 }

 printf("클라이언트로부터 접속을 기다리고 있습니다...\n");

 cs = accept(s, (sockaddr*)&client, &size);
//한명의 클라이언트만 접속을 받는다.

 if( cs == INVALID_SOCKET)
 {
  closesocket(s);
  Error("accept");
  return;
 }

 printf("클라이언트가 접속되었습니다.\n");
 printf("IP = %s, PORT = %d\n",
  inet_ntoa(client.sin_addr), ntohs(client.sin_port) );

 while(1)
 {
  int num = recv(cs, value, 256,0);        //클라이언트에게 메시지를 받는다.
  if(num == 0 || num == SOCKET_ERROR) //에러 확인
   break;
  printf("%s 수신\n",value);
  int num2 = send(cs, value, 256,0);     //그것을 다시 돌려준다.
 }

 closesocket(cs);
 closesocket(s);
 WSACleanup();
}

void Error(char* szMessage)
{
 printf("Error:[%d] %s \n", WSAGetLastError(), szMessage);
 WSACleanup();
 exit(0);
}


//TCP기반의 네트워크
//made by chessire

#include<iostream>
#include<winsock2.h>

#pragma comment(lib, "ws2_32.lib")

void Error(char* szMessage);

void main()
{
 SOCKET s;
 WSADATA wsaData;
 SOCKADDR_IN server;
 char value[256];
 ::ZeroMemory(value, sizeof(char)*256);

 WSAStartup(MAKEWORD(2,2), &wsaData);
 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

 if(s == INVALID_SOCKET)
 {
  Error("socket");
  return;
 }

 server.sin_family = AF_INET;
 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 server.sin_port = htons(10000);

 if( connect(s, (sockaddr*)&server, sizeof(server)) != 0 )
 {
  closesocket(s);
  Error("connect");
  return;
 }
 printf("127.0.0.1의 10000번 포트에 접속을 성공.\n");

 while(1)
 {
  char value2[256];
  printf("할말 입력(q is quit) : ");
  scanf("%s",value);
  if(!strcmp(value,"q") || !strcmp(value,"Q"))
   break;
  send(s, value,256,0);
  if(recv(s, value2,256,0) == 0)
   break;
  printf("%s\n",value);
 }
 puts("Received file data");
 send(s,"Thank you", 10, 0);
 closesocket(s);
 WSACleanup();
}

void Error(char* szMessage)
{
 printf("Error:[%d] %s\n", WSAGetLastError(), szMessage);
 WSACleanup();
 exit(0);
}

'Notes > Tech History' 카테고리의 다른 글

싱글턴 클래스  (0) 2011.10.17
OpenAL의 시작  (3) 2010.12.02
리눅스 기본 명령어  (1) 2010.08.17
소켓의 프로토콜 (socket함수를 파헤쳐보자)  (0) 2010.08.16
윈도우 기반의 소켓관련 함수  (0) 2010.08.14

ls - 도스의 "dir"과 같은 역할, 해당 디렉토리에 있는 파일의 목록을 나열한다.

cd - 작업 디렉토리를 이동한다.

pwd - 현재 작업 디렉토리의 전체 경로를 출력한다.

rm - 파일이나 디렉토리를 삭제한다. 해당 파일이나 데릭토리에 삭제 권한이 있어야 한다.

cp - 파일이나 디렉토리를 복사한다. 새로 복사한 파일은 사용자의 소유가 된다.

touch - 크기가 0인 새 파일을 생성하거나 이미 존재하는 파일인 경우 수정시간을 현재시각으로 변경한다.

mv - 파일과 디렉토리의 이름을 변경하거나 위치 이동 시 사용한다.

mkdir - 새로운 디렉토리를 생성한다. 생성된 디렉토리는 명령어를 수행한 사용자의 소유가 된다.

rmdir - 디렉토리를 삭제한다. 해당 디렉토리의 삭제 권한이 있어야 하며, 파일이 들어 있으면 안된다. 파일이 들어있는 디렉토리를 삭제하려면 "rm -r"을 사용해야 한다.

cat - 텍스트로 작성된 파일을 화면에 출력한다. 파일의 내용을 간단히 확인하기 위해서 주로 사용한다.

head - 텍스트로 작성된 파일의 앞 10행을 출력한다.

tail - 텍스트로 작성된 파일의 뒤 10행을 출력한다.

more - 텍스트로 작성된 파일을 화면에 페이지 단위로 출력한다.
        - Spacebar는 다음페이지, b는 앞페이지, q는 종료이다.

less - more와 용도가 비슷하지만 기능이 더 확장된 명령이다. more의 키 및 화살표, Page Up, Page Down도 작동한다.(vi의 기능이 일부 추가되었다고 보면된다.)

file - File이 어떤 종류의 파일인지 표시해 준다.

clear - 명령창을 깨끗하게 지워준다.