본문 바로가기
Delphi Tip/통신

델파이 기본 소켓의 사용

by MonoSoft 2024. 1. 2.
728x90
반응형

델파이 기본 소켓의 사용

728x90

 

 

TCP/UDP 란?

 

TCP

 

연결지향 프로토콜이다.

연결을 시도해 연결이 성공하면 일종의 터널링이 확보되어

이 터널을 통하여 데이터를 전송하고 받는다.

전송된 데이터의 무결성이 확보된다.

데이터의 전송이 제대로 되지 않을 경우에는 목적지에 제대로 전송될때까지 반복한다.

안정적인 데이터 전송을 원할경우에 이를 사용한다.

 

 

UDP

 

User Datagram Protocol 이라고 불리운다.

전송된 데이터가 중간에 유실될 수도 있고, 순서가 뒤바뀔 수도 있다. 환장한다.

그럼 왜 쓰나? 속도가 빠르다. 데이터의 안정성을 잃어버리는 대신에 속도를 보장한다.

멀티미디어 데이터 전송부분에서 종종 사용된다.

 

 

프로토콜이란?

 

일반(형식, 종료문자)

 

프로토콜이라 함은 TCP/UDP 이외에도 사용자가 정의한 (물론 TCP/UDP 기반위에서..)

프로토콜도 포함된다.

예를 들어서 클라이언트가 서버에 메세지를 보낸다고 하자.

특정 메세지에 따라서 서버는 각기 다른 작업을 해야한다.

 

if 'Start_Service' then begin

// 채팅서비스를 시작한다.

end

else

if 'Stop_Service' then begin

// 채팅 서비스를 종료한다.

end

else

if 'Login' then begin

// 사용자의 로그인 정보를 저장한다.

end;

 

여기서 if 문 안의 string 가 프로토콜이다.

보통 클라이언트 측에서

 

SendText('Start_Service'); 등의 형식으로 보낸다.

프로토콜은 개발자가 정하기 나름이므로 위와 같이

바로 읽어 해독이 가능한 string를 사용하기도 하고

별도의 해독과정을 거치는 문자열등을 사용하기도 한다.

물론 이때는 정해진 규약이 있어야 한다.

 

Start_Service : '0001'

SendText('0001'); 이라는 메세지를 보내면 서버에서는 Start service 로 인식하면 된다.

 

맘대로 정해서 사용해보자.

내 경험상 프로토콜은 바로 이해할 수 있는것이 중간 과정을 안거치고 좋은것 같다.

 

자, 내가 서버에 현재 사용자들의 리스트를 요구했다고 치자.

홍길동/33세/서울/남자

이혁/16세/부산/호모 // -_-;; 하춘화/55세/뉴욕/여자

유지태/9세/섬/외계인

 

이상의 사용자 정보가 있다고 치자.

각각 사용자 정보의 길이가 다르다.

또한 어디까지가 홍길동의 정보이고 어디까지가 이혁의 정보인지 구분해 내야한다.

어떻게?

우리는 여기서 '/'를 정보 구분용으로 이용한다고 치자.

하나의 정보뒤에는 '*'을 붙이도록 하자.

(실제 코딩에서는 하지말자. 위의 예의 문자들은 프로토콜로 안좋다.

프로토콜은 사용자가 입력할 수 없는 문자들로 이루어져야 한다.)

 

SendText('홍길동/33세/서울/남자*');

SendText('이혁/16세/부산/호모*');

 

자 이렇게 하면 된다.(파싱은 알아서 하도록..)

어라? SendText 인데 받는쪽에서 ReceiveText 하면 하나씩 읽힐텐데 왜 '*'을 붙이냐??

 

일정 시간의 term 을 두고서 전송한다면 ReceiveText 만으로도 훌륭하다.

하지만 연속된 string 의 전송은 str1 과 str2 를 붙어버린다.

따라서 str1 과 str2 의 구분을 위해서

하나의 프로토콜이 끝났음을 알리는 종료문자가 필요하다.

 

암호화

 

자 이제 간단한 프로토콜 전송을 예로 보자.

 

Client:

SendText('Get_User_Info*');

 

Server:

위의 메세지를 받고서,

SendText('홍길동/33세/서울/남자*');

SendText('이혁/16세/부산/호모*');

이들 패킷은 간단하게 누군가에게 노출될 수 있다.

 

자 그럼 어떻게 해야 노출이 안될까?

자신만의 encode 방식으로 종료문자를 제외한 문자열을 암호화하도록 하자.

 

어디까지가 하나의 프로토콜인지를 알기 위해선 종료문자는 유지해야 한다.

 

'ksjflj204ruw0#@%3632^@##^!*'

 

자 이렇게 왔다.

내가 만든 프로토콜이니 decode 만 하면 훌륭하게 홍길동 정보가된다.

 

물론 암호화된 문자열의 중간에는 절대로 종료문자가 없어야 한다.

있으면 곤란하쥐~

 

이유 묻지마라. 이유 물을려면 코딩에서 손떼라.

 

 

프로토콜 체크

 

흔히 방대한 네트웍 프로토콜의 해석상에서 문제가 발생한다면

프로토콜 체크가 허술해서이다.

 

내가 보낸 프로토콜에 string 가 하나라도 틀린게 없는지 검사해야 한다.

검사한후에 다음 routine 을 돌도록 하자.

 

특히 공백, 엄청나게 긴 string 등을 엄격하게 체크하라.

하기 싫으면 하지 않아도 된다.

하지만 당신의 네트웍 프로그램은 안정성과 멀어진다.

 

다소의 CPU 리소스를 검사에 할당하더라도

안정적으로 프로그램을 만들어라.

안정적이지 않은 프로그램은 상용화하기 어렵고

누구도 사용하지 않는다.

 

 

데이터 전송

 

 

SendText

와우~ 정말 추천해 주고 싶은 방법이다.

얼마나 간단한가? 이것만큼 손쉬운 방법은 없을것이다.

특히 Text protocol 을 전송시에 100% 사용한다.

데이터 전송에도 사용하긴 하지만 데이터를 string 로 변환을 해야하는 것 때문에

그다지.....어느 외국애의 파일전송 샘플을 보면 SendText 를 통해서 파일을 전송하더라.

 

 

SendBuf

난 이것을 주로 사용한다.

데이터 전송에는 이것만한 것이 없다.

SendBuf 의 도움말을 잘 보도록 하자.

소켓 버퍼에 다른값이 있어서 쓰기가 안될경우 -1 을 리턴한다.

물론 전송은 안된다.

에잉~ 난 전송해야 하는데..안되면..이거 못쓰쥐....

이런 분이라면 아래를 봐라.

 

While SendBuf()= -1 do begin

end;

 

이러면 확실하게 전송된다.

하지만 조심해서 사용해야 한다.

일정한 Network Bandwidth 에서 소켓의 사용량이 많을 경우

루프를 계속 돌아버림으로써 CPU 의 오버헤드를 가져온다.

 

중간중간 패킷의 유실이 있어도 상관없다면

while 문 없이 SendText 가 위의 while 문 사용한것과 같다.

 

 

SendStream

 

초기에 이거 사용하다가 에러 뻑뻑 터진다.

에잉? 왜 터져?

 

SendStream 에 Ctrl + MouseClick 해봐라.

지가 보내고 나서 알아서 해제한다. stream 을...

따라서 Stream.Free 가 필요없다.

한번 보내기에는 적절하지만 같은 데이터를

두번보내기에는 사용하지 않는다.

 

데이터 받기

 

ReceiveText

 

캬~ 자주 보는 method 이다.

Text protocol 에서 주로 사용된다.

이것에 대해선 특별하게 설명하지 않는다.

 

 

ReceiveBuf(소켓 버퍼 이야기) 

RcvSize:=Socket.ReceiveLength;

RcvSize:=Socket.ReceiveBuf(Buf, RcvSize);

단짝이다. 두개를 절대 떨어뜨리지 마라.

 

ReceiveLength 를 또한 100% 믿지마라.

위의 두개의 RcvSize 가 다른경우가 종종있다.

 

아랫놈이 믿을만한 놈이다.

1G 짜리 파일 전송해봤는가?

 

Send 부분과 Receive 부분을 적절하게 사용하지 않는다면

깨진 파일만 받게될 것이다 .

또한 내가 전송된 데이터의 크기가 소켓버퍼보다

클경우를 대비해서 전역버퍼를 이용한다.

소켓 버퍼보다 클경우 잘라서 받기 때문이다.

 

보통 소켓의 기본버퍼 사이즈는 8Kbyte(8192 byte) 이다.

 

 

예외의 데이터 처리(Nimda, the Trojan Horse) 

 

이 부분은 특히 Text protocol 과 관련된 부분이다.

내가 80 port 를 이용할 경우 별쓰잘데 없는 놈들(Nimda)까지 데이터를 보낸다.

물론 그 string 중에는 프로토콜과 유사한 놈들도 있다.

이래서 검사를 확실히 하라는 것이다.

에이~ 그럼 80 port 안쓰면 되지머~ 흥!!

젠장...니 눈에는 Nimda 만 보이냐?

트로이 목마 프로그램들은 80 이외의 수많은 포트(만든놈이 지정)를 이용한다.

당신이 사용하는 port(short integer --> 65365) 에 데이터를

전송안하리란 법이 있냐? port 에 관한 이야기는 밑으로 미루자.

 

 

에러처리

 

별거 없다.

OnErrorEvent 에 다음의 두줄을 추가하자.

ErrorCode:=0;

Socket.Clsoe;

 

네트워크

 

- IP(공인/사설, 유동/고정) IP ? IP !

IP 는 인터넷을 여행하기 위한 고유번호이다.

IP 없이 인터넷을 여행할 수 없다.

자 분류해보자.

 

일단 공인(Public)/사설(Private).

공인 IP 는 고유의 IP 를 가지고 인터넷을 여행하는 것이다.

사설? Subnet 에서 사용하기 위해서 만든 IP 이다. 보안, IP 부족등의 이유로 사용된 다.

하지만 인터넷을 여행할때는 상위 장비의 IP 를 가지고 여행을 한다.

다시 말해 수십, 수백(~255)의 사용자가 동일한 IP 를 가지고 있다

 

728x90
반응형

댓글