- 소켓 생성
server_socket = socket(PF_INET, SOCK_STREAM, 0);
옵션이 0이면 블로킹모드이다. 블로킹모드는 recv()함수에서 리턴하지 않고 기다린다.
-아래와 같이 timeout을 주면 일정 시간 후에 타임아웃 에러낸다.
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
-아래와 같이 select함수에서 timeout 에러를 낼 수도 있다.
보통 select에 타임아웃을 많이 준다.
tv.tv_sec = 10; // 10초 timeout
tv.tv_usec = 0;
int ret = select(sock + 1, &read_fds, NULL, NULL, &tv);
참고로
int ret = select(sockfd + 1, &readfds, &writefds, NULL, &timeout);
일시 writefds는 항상 true이기 때문에 return되고 timeout은 무시됨.
select함수의 timeout은 주기를 뜻하는거지 에러를 뜻하는게 아님.
타임아웃을 보통 0.1~1초로 줘서 빨리 루프를 돌게 만듬.
보통 writefds는 설정하지않고 has_to_send 같은 변수를 추가로 설정해서 같이씀.
안그러면 send()로직을 계속 실행 할것이기 때문
TCS, UCS 코드
// tcp_polling_sender.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/time.h>
#include <netinet/in.h>
#define POLLING_INTERVAL 1800 // 3분 = 1800 x 0.1초
#define BUF_SIZE 1024
// 전역 변수
int has_data_to_send = 0;
char send_buf[BUF_SIZE] = {0};
// --- TCS에서 tpcall() 호출될 때 실행됨 ---
int svc_main(int svc, char *in_buf, int in_len, char *out_buf, int *out_len) {
printf("[TCS 수신] 전문 수신: %s\n", in_buf);
strncpy(send_buf, in_buf, sizeof(send_buf) - 1);
send_buf[sizeof(send_buf) - 1] = '\0';
has_data_to_send = 1;
strcpy(out_buf, "OK");
*out_len = strlen(out_buf);
return 0;
}
// --- 메인 루프: select로 송수신 처리 ---
int usermain(int argc, char **argv) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
// 소켓 연결 설정
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12345); // 포트 설정
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
int tick = 0;
while (1) {
fd_set readfds, writefds;
struct timeval timeout;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(sockfd, &readfds);
if (has_data_to_send) {
FD_SET(sockfd, &writefds);
}
timeout.tv_sec = 0;
timeout.tv_usec = 100000; // 0.1초
int ret = select(sockfd + 1, &readfds, &writefds, NULL, &timeout);
if (ret > 0) {
// 수신 처리
if (FD_ISSET(sockfd, &readfds)) {
char recv_buf[BUF_SIZE] = {0};
int len = recv(sockfd, recv_buf, sizeof(recv_buf), 0);
if (len > 0) {
printf("[TCP 수신] %s\n", recv_buf);
}
}
// 송신 처리
if (has_data_to_send && FD_ISSET(sockfd, &writefds)) {
int sent = send(sockfd, send_buf, strlen(send_buf), 0);
if (sent > 0) {
printf("[TCP 송신] %s\n", send_buf);
has_data_to_send = 0;
}
}
}
// --- 3분마다 polling 전문 전송 ---
tick++;
if (tick >= POLLING_INTERVAL) {
tick = 0;
// 예시: "1001 POLLING"
snprintf(send_buf, sizeof(send_buf), "1001 POLLING\n");
has_data_to_send = 1;
printf("[POLLING 발생] 전문 생성 완료\n");
}
}
close(sockfd);
return 0;
}
timeout을 0.1초로 줬기에 rick은 0.1초에 1씩 쌓인다. 그래서 1800이 되면 3분 타임아웃이난다.
extern int has_data_to_send;
선언이 아니라 이 변수 어딘가엔 있겠지란 선언. 순서 상관 없다.
'네트워크, 보안' 카테고리의 다른 글
10. 네트워크 관리사 합격 후기 (0) | 2020.05.24 |
---|---|
9. 네트워크관리사 실기 정리 (3)- 라우터 설정 (0) | 2020.04.17 |
8. 네트워크관리사 실기 정리 (2)- 단답형 문제 (TCP/IP, 리눅스, 신경향) (0) | 2020.04.16 |
7. 네트워크관리사 실기 정리 (1)- 다이렉트 케이블, windows 2008 server R2 실습문제 (0) | 2020.04.13 |
6. 아파치 톰캣(apache tomcat) 메모리 현황을 jmx remote로 모니터링 하기 (2) | 2019.12.30 |