socket 프로그램에서...
글쓴이: koonpal / 작성시간: 토, 2003/03/22 - 2:28오후
제가 초보라...^^
socket 프로그램에서 있잖아요...
예를 들어 int형 데이터를 보내던지.. char형 데이터를 보내던지...
소켓을 만들어 하나의 데이터형을 클라이언트 프로그램에서 서버 프로그램으로 보내는데는 문제가 없는데요...
제가 잘 모르겠는것은...
클라이언트에서 소켓을 만들어서...
먼저 char형 데이터를 보내고 그 다음 int형 데이터를 보낼려고 하거든요...
그러니까 서로 다른 데이터형을 하나의 소켓을 연 후 클라이언트에서 서버로 보낼려고 할려면 어떻게 하면 되죠...
그건 잘 모르겠네요...
부탁을 드리겠습니다...
Forums:
잘 돌아가는 Program을 올려 주세요.수정해 봅시다.
잘 돌아가는 Program을 올려 주세요.
수정해 봅시다.
---
http://coolengineer.com
구조체를 만들어서 데이터를 넣어준다음char 형의 버퍼를 만들어서 그
구조체를 만들어서 데이터를 넣어준다음
char 형의 버퍼를 만들어서 그 버퍼에
memcpy로 복사해준다음 보내주는 방법과
버퍼가 있으면 직접 그 버퍼에 데이터를
카피해주는 방법이 있습니다..
코드가 이런데 좀 봐 주실래요...
위의 코드 처럼 했는데요...
int형은 보낼 수 있을 거 같은데...
이다음 곧바로 char 형을 보낼려고 하거든요...
어떻게 해야 될지 몰라서요...
부탁을 드립니다...
Re: 코드가 이런데 좀 봐 주실래요...
전송은 4*20 byte가 될 것이구요.
수신도 4*20 byte를 기대하지만, 한번 보낸것이 한번에 읽힌다는 보장이 없으므로 위험한 방법입니다.
무슨 프로젝트에 쓰실것이 아니고, 단지 test만 해보실 것이면, 뒤에 이어
이렇게 전송하시면 됩니다.
---------------------
프로젝트에 쓰실 것이라면, 전송은 간단해 보이지만, 수신할 때는 고려사항이 많습니다. 한번에 수신이 안되는 경우도 있으니까요.
대개 패킷을 만들때는 line 단위로 할 것이냐와 block으로 할 것이냐를 고려합니다.
위와 같이 int가 직접 block 단위로 전송하는 모습은 yhjj777님께서 말씀하신것처럼 struct를 만들어 packet을 정의하고
송수신을 하는 것이 좋습니다.
복잡해지면 packet이 여러 종류가 생기고, 그 크기도 다양하게 되는데,
그런 것을 대비하여 packet 앞부분에 전체 크기를 넣어서 전송합니다.
수신하는 쪽에서도 크기에 해당하는 부분만 먼저 읽고,
나머지가 채워질 때까지 수신하는 방법을 사용하지요.
이런 것 때문에,
패킷 type,
패킷 완성 timeout
등이 프로토콜 설계시에 들어갑니다.
그밖에, int 같은 데이터를 보낼때는 되도록, network byte order (htonl)로
변환하여 보내는 것이 좋구요. 아니면, 아예 sprintf 같은 것으로 string으로 바꾸어 전송하여, 디버깅이 쉬운 model로 만들기도 합니다.
또, int 와 character가 섞일 경우 packet 설계할 때, alignment 때문에
hole이 생기는 경우도 있으므로 조심하셔야하지요..
두서없이 썼습니다.
---
http://coolengineer.com
큰 메세지를 한번에 받으려면..
보통 큰 메세지는 한번의 read(sockfd, &info, sizeof(info)); 호출로는 받아올 수 없습니다.
제 경우읽는 클러스터 내에서 큰 메세지를 전송했는데,,
1137bytes 정도씩 끊어져서 여러번 read 를 호출해야 모두 읽어 올 수 있더군요.
이때 read() 대신 recv()를 쓰면 한번의 send()로 보낸 메세지를 한번에 읽어올 수 있습니다.
recv(sockfd, buf, len, MSG_WAITALL);
과 같이 MSG_WAITALL 플래그를 세팅하면 한번의 recv 호출로 메세지를 끝까지 읽어올 수 있습니다.
제 경우는 클러스터 내에서의 전송이긴 했지만,,
1MB 정도는 한번에 읽어지더군요..
===============
Vas Rel Por
저 근데...
저...
그런데...
하나의 connection으로 int형과 char형을 보낼려고 합니다...
어떻게 해야 하죠...
제가 모르른게 이거라서...
동시에 두개의 데이터형을 보내는 것을...
잘 이해가 안되어서...
부탁을 드립니다...
[code:1]struct pkt{ in
정도로 보내면.. 되겠죠?
---
http://coolengineer.com
socket은 특별히 int와 char 등 보내는 데이터형을 구별하지 않
유닉스 계열에서는 그냥 일반파일에 쓰시는 것처럼 쓰시면 됩니다.
sd 가 정상적으로 연결된 소켓 디스크립터라고 하면,
일반 파일 디스크립터 쓰는 것처럼,
write(sd, &char_var, 1);
이라고 쓰면 char 하나를 쓰고,
write(sd, &int_var, sizeof(int));
라고 하면 integer 를 보내고,
write(sd, string_var, strlen(string_var));
식으로 쓰면 스트링을 보냅니다.
앞에서 예제로 보여주신 것처럼 structure 를 보내셔도 되고요,,
다만 소켓 통신하는 상대방이 자기와 같은 장비라는 보장이 없으니
바이너리 자료포멧(endian), structure 패딩 등 여러가지를
신경써 주셔야 하며, 보낼 때 한번에 n byte보냈다고
받을 때도 한번에 n byte 받는다는 보장이 없으니 read/write시에
제대로 원하는 만큼 전송될 수 있도록 코드를 짜 주셔야 할겁니다.
다 앞에서 말씀해 주셨던 내용이고요,,
소켓에서는 보내는 쪽과 받는 쪽에서 서로 읽는 방식만 잘 맞춰준다면
어떤 데이터를 어떻게 섞어서 보내셔도 문제없습니다.
주의) 바이트 순서
문자열로만 전송하는 경우에는 문제가 없지만
int, long등을 전송하는 경우에는 반드시 바이트 순서를 고려해야 합니다.
다름아닌 Big endian, Little Endian인데요. 이는 하드웨어(CPU) 설계문제 때문에 생긴것입니다.
운영체제 수준에서 어느정도 해주기도 하지만
이를테면 유닉스 호환등은 Big Endian, java머신은 Big Endian
윈도우즈계열은 little Endian을 사용합니다.
따라서, 정석은 네트웤상으로 전송시는 표준형으로 표현하여 보내고, 자신의 호스트에서는 호스트에 맞는 형태로 변경하여 사용해야 합니다.
htons(), htonl(), ntohs(), ntohl()을 참고하시고, XDR을 참고하시면 되겠습니다.
참고:
Big Endian : Risc계열 프로세서, 모토롤라계열 프로세서(리눅스, 유닉스, 자바등)
little Endian : Intel계열 프로세서(윈도우등)
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
Re: 주의) 바이트 순서
혹시나 오해가 있을까봐, 보충합니다. 먼저 빅 인디언, 리틀 인디언은 CPU에
가장 큰 영향을 받습니다. 즉, 리눅스도, intel 용으라면 리틀 인디언,
스팍용이라면, 빅 인디언 구조입니다. 그런데, 자바의 경우는 안에서 자체적으로
빅 인디언 구조로 만들어줍니다. 그럼 고운 하루되시길...
=========================
CharSyam ^^ --- 고운 하루
=========================
댓글 달기