소켓 통신에서 데이터 주고 받기 잘 하다가 에러납니다.
아래 코드를 보시면,
소켓의 서버와 클라이언트 통신에서,
클라이언트의 특정 명령에 의해 서버는 많은 양의 데이터를 내려줍니다.
많은 양이라는 것은, #define 돼어 있는 BLOCK_SIZE 만큼 N번 반복한다는 것입니다.
예를 들어, BLOCK_SIZE가 512개이고, 1024번 반복 한다면, 보내는 데이터의 타입이 unsigned int이므로, 4 x 512 바이트만큼 1024번 보내도록 하는 것입니다.
그런데 재밌는 것은,
BLOCK_SIZE를 128 또는 256 으로 해 놓으면, 통신에 문제가 없습니다. (생각보다 느리긴 하지만)
그런데 512로 하면서 부터 서버가 보낸 데이터를 클라이언트가 놓친다는 것입니다.
놓치는 건지, 어디 부하가 걸리는건지, 데이터가 꼬이는건지, 원인 파악이 쉽지 않습니다.
만약에 서버쪽에서 데이터를 보내거나, 클라이언트로부터 다음 명령을 받을 때에, usleep 으로 딜레이를 주면,
그렇지 않을때보다 더 많이 날라갑니다.
딜레이를 주기 전에 50번째 블럭까지 잘 날라가다가 51번째 블럭에서 일그러졌다면,
딜레이를 주었을 때는 그 보다 많은 80번째 블럭까지는 잘 날라가더란말입니다.
이 블록의 카운트 역시 일정하지는 않습니다.
참고가 될만한 자료나 조언 부탁드리겠습니다. --꾸뻑
-- 아래 --
client 소스
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 5500
#define BLOCK_SIZE 512
#define N 1024
//#define DEBUG
#define DTIME
#ifdef DEBUG
#define dp(fmt,args...) printf( fmt, ## args )
#define dlp(fmt,args...) printf( "[%s][%04d] " fmt, __FILE__,__LINE__, ## args )
#else
#define dp(fmt,args...)
#define dlp(fmt,args...)
#endif
typedef struct
{
unsigned short id;
unsigned short length;
}__attribute__ ((packed)) _req;
typedef struct
{
unsigned short id;
unsigned short length;
unsigned int index;
unsigned int block;
unsigned short wlength;
unsigned int data[BLOCK_SIZE];
}__attribute__ ((packed)) _ad;
typedef struct
{
unsigned short id;
unsigned short length;
unsigned int sec;
unsigned int sec7;
unsigned char indicator;
unsigned char satNum;
unsigned int latitude;
unsigned int longitude;
}__attribute__ ((packed)) _gps;
typedef struct
{
unsigned short id;
unsigned short length;
unsigned char ack;
}__attribute__ ((packed)) _msg;
void dtp(char* str)
{
#ifdef DTIME
struct timeval tv;
gettimeofday(&tv, NULL); printf("%10s : %ld.%06ld\n", str, tv.tv_sec, tv.tv_usec);
#endif
}
int main(int argc, char **argv)
{
int i;
int client_len;
int client_sockfd;
unsigned int txBuf[BLOCK_SIZE];
unsigned int rxBuf[BLOCK_SIZE];
struct sockaddr_in clientaddr;
_gps gps;
_req req;
_ad ad;
_msg msg;
if (argc != 2)
{
printf("Usage : ./zipcode_cl [port]\n");
printf("예 : ./zipcode_cl 4444\n");
exit(0);
}
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr(argv[1]);
clientaddr.sin_port = htons(PORT);
client_len = sizeof(clientaddr);
if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) < 0)
{
perror("Connect error: ");
exit(0);
}
for(i=0; i
read(client_sockfd, (char*)&msg, sizeof(msg));
req.id = htons(0x010B);
req.length = htons(0x0000);
write(client_sockfd, (char*)&req, sizeof(req));
if(read(client_sockfd, (char*)&gps, sizeof(gps))<=0)
{
printf("Error\n");
exit(0);
};
// printf("gps.id = 0x%04X\n", htons(gps.id));
if(htons(gps.id) == 0x030D)
{
req.id = htons(0x050B);
for(i=0; i
{
//usleep(100000);
write(client_sockfd, (char*)&req, sizeof(req));
//usleep(100000);
if( (read(client_sockfd, (char*)&ad, sizeof(ad)) > 0) )
{
// printf("ad.id = 0x%04X\n", htons(ad.id));
if(htons(ad.id) != 0x030E)
{
printf("Error (count = %d)\n", i);
i = N;
}
}
}
}
/*
dtp("start");
for(i=0; i
{
write(client_sockfd, (char*)txBuf, sizeof(txBuf));
// read(client_sockfd, (char*)rxBuf, sizeof(rxBuf));
dlp("rx[%d] = %d\n", BLOCK_SIZE-1, rxBuf[BLOCK_SIZE-1]);
}
dtp("end");
*/
close(client_sockfd);
exit(0);
}
server 소스
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 5500
#define BLOCK_SIZE 512
#define N 1024
//#define DEBUG
#define DTIME
#ifdef DEBUG
#define dp(fmt,args...) printf( fmt, ## args )
#define dlp(fmt,args...) printf( "[%s][%04d] " fmt, __FILE__,__LINE__, ## args )
#else
#define dp(fmt,args...)
#define dlp(fmt,args...)
#endif
typedef struct
{
unsigned short id;
unsigned short length;
unsigned char ack;
}__attribute__ ((packed)) _msg;
typedef struct
{
unsigned short id;
unsigned short length;
}__attribute__ ((packed)) _req;
typedef struct
{
unsigned short id;
unsigned short length;
unsigned int index;
unsigned int block;
unsigned short wlength;
unsigned int data[BLOCK_SIZE];
}__attribute__ ((packed)) _ad;
typedef struct
{
unsigned short id;
unsigned short length;
unsigned int sec;
unsigned int sec7;
unsigned char indicator;
unsigned char satNum;
unsigned int latitude;
unsigned int longitude;
}__attribute__ ((packed)) _gps;
void dtp(char* str)
{
#ifdef DTIME
struct timeval tv;
gettimeofday(&tv, NULL); printf("%10s : %ld.%06ld\n", str, tv.tv_sec, tv.tv_usec);
#endif
}
int main(int argc, char **argv)
{
int i;
int server_sockfd, client_sockfd;
int state, client_len;
struct sockaddr_in clientaddr, serveraddr;
_msg msg;
_req req;
_gps gps;
_ad ad;
unsigned int txBuf[BLOCK_SIZE];
unsigned int rxBuf[BLOCK_SIZE];
state = 0;
// internet 기반의 소켓 생성 (INET)
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error : ");
exit(0);
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(PORT);
state = bind(server_sockfd , (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (state == -1)
{
perror("bind error : ");
exit(0);
}
state = listen(server_sockfd, 5);
if (state == -1)
{
perror("listen error : ");
exit(0);
}
signal(SIGCHLD, SIG_IGN);
client_len = sizeof(clientaddr);
for(i=0; i
while(1)
{
client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &client_len);
if (client_sockfd == -1)
{
perror("Accept error : ");
exit(0);
}
else
{
state = 1;
msg.id = 0x0401;
msg.length = 0x0001;
msg.ack = 0x01;
write(client_sockfd, (char*)&msg, sizeof(msg));
printf("accepted\n");
}
gps.id = 0x030D;
gps.length = 18;
gps.sec = 1;
gps.sec7 = 2;
gps.indicator = 3;
gps.satNum = 4;
gps.latitude = 5;
gps.longitude = 6;
ad.id = 0x030E;
ad.length = BLOCK_SIZE * 4 + 10;
ad.index = 1;
ad.block = N;
ad.wlength = BLOCK_SIZE * 4;
for(i=0; i
if(read(client_sockfd, (char*)&req, sizeof(req)) > 0)
{
printf("id : 0x%04X\n", req.id);
if(req.id == 0x010B)
{
write(client_sockfd, (char*)&gps, sizeof(gps));
dtp("start");
for(i=0; i
{
//printf("wait req \n");
if(read(client_sockfd, (char*)&req, sizeof(req)) > 0)
{
// printf("id : 0x%04X\n", req.id);
if(req.id == 0x050B)
{
ad.index = i+1;
write(client_sockfd, (char*)&ad, sizeof(ad));
}
}
//printf("count = %d\n", i);
}
dtp("end");
}
}
/*
while(state)
{
memset(rxBuf, '\0', sizeof(txBuf));
if (read(client_sockfd, (char*)rxBuf, sizeof(rxBuf)) <= 0)
{
state = 0;
close(client_sockfd);
break;
}
dlp("rx[%d] = %d\n", BLOCK_SIZE-1, rxBuf[BLOCK_SIZE-1]);
write(client_sockfd, (char*)txBuf, sizeof(txBuf));
}
*/
}
close(client_sockfd);
}
..
그냥 같은 쓰레드에 올려 주셨으면 좋았을텐데... 이렇게 코드를 올려주시면 아마 도움 받기 힘들지 않을까 생각됩니다. 제 생각에는 데이터를 송수신 하는 방법의 차이인것 같습니다. 즉, 통신 코드 자체를 다른 모델로 한번 바꿔 보시면 어떨지 생각됩니다. 문의 하신 내용은 그렇게 시간이 걸릴 이유가 없는 부분입니다. 가장 빠르게 접근 하시는 방법은 제 생각에....
1. 모든 코드를 지운다.
2. 원하는 통신 프레임을 만든다.
3. 가장 간단한 데이터를 반속해서 전송해본다.
4. 여기에 원하는 데이터 형식/방식을 적용해본다.
이렇게 한번 해보시는게 어떨까 생각됩니다. 그리고 올려주신 내용을 보니 TCP/IP 통신이신것 같은데 데이터의 유실은 발생하지 않습니다. 또한 놓쳐서도 않되는 데이터죠. 한번 통신 프레임을 만들어 보시면 어떨까 생각됩니다. 가장 손쉽고 간단한것부터 한번 시도해보세요.
행운을 빕니다.
P.S : 통신 프레임에서는 이벤트 기반의 동작이기 때문에 타이머나 SLEEP을 줘야 할때는 다른 용도입니다. 즉, 읽기/쓰기 동작이 SLEEP같은것으로 방해를 받아서는 않됩니다.
/* include readn
stream에 대해 공부하세요. 특히, read/write의 특성에 대해 공부하시고, 왜? readn(), writen()이 필요했는가를 검토하세요.
이 주제는 수 년째 다뤄진 질문이므로, 게시판을 잘 ~ 찾으셔도 될 듯합니다.
작성하신 소스에서 write(), read()를 아래의 writen(), readn() 으로 바꿔서 코딩하시고 테스트하세요.
* 아래 코드는 절대로 제가 짠게 아니고 퍼온 코드입니다. 구글검색으로 ... 아마도, 스타일로 봐서는 스티븐스의 유닉스네트워크프로그래밍의 코드로 보입니다만.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
댓글 달기