내용도 너무 오래 되었음 수정해야함.
이제 memrecver 에 소켓연결후 syslog 메시지를 전송하는 memsender 를
제작해 보도록하자, 보통의 파일을 열어서 읽은 다음에 소켓으로 전송하는
일반적인 루틴을 가지고 있지만, 파일의 마지막라인을 만나더라도,
파일 연결지시자를 계속 유지하고 있다가 새로운 내용이 추가되면 다시 read 해야
하므로(이를테면 tail 에 -f 옵션을 준것과 비슷한), select(2) 를 통해서 이를
구현하도록 하겠다.
select 는 입출력다중화를 위한 목적으로 주로 쓰이며, 네트웍 프로그래밍에서
다중 클라이언트를 받아들이는 서버제작 기법으로 많이 활용된다.
예제: memsender.c
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 12345
#define PACKET_SIZE 255
int main()
{
int fd;
int n;
int state;
int client_len;
int client_sockfd;
int i;
FILE *fp;
char *buf;
char l_buf[1];
struct sockaddr_in clientaddr;
struct timeval tv;
fd_set readfds;
if((fd = open("/var/log/meminfo", O_RDONLY)) == -1)
{
perror("file open error : ");
exit(0);
}
// memrecver 서버에 연결을 위한 소켓생성및 연결
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr("127.0.0.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);
}
fp = fdopen(fd, "w");
buf = (char *)malloc(PACKET_SIZE);
i = 0;
while(1)
{
tv.tv_sec = 0;
tv.tv_usec = 10000;
state = select(2, &readfds, (fd_set *)0, (fd_set *)0, &tv);
switch(state)
{
case -1:
perror("select error : ");
exit(0);
default :
memset(buf, 0x00, PACKET_SIZE);
while ((n = read(fd, l_buf, 1)) > 0)
memset(buf, 0x00, PACKET_SIZE);
while ((n = read(fd, l_buf, 1)) > 0)
{
buf[i] = l_buf[0];
if (l_buf[0] == '\n')
{
write(client_sockfd, buf, i+1);
printf("-->%s", buf);
memset(buf, 0x00, PACKET_SIZE);
i = 0;
continue;
}
i++;
}
break;
}
}
close(fd);
}
select 가 들어간것만 빼고는 매우 일반적인 프로그램이므로 설명은 생략하도록
하겠다.
소켓관련 프로그래밍은 셈플로 알아보는 소켓프로그래밍(1)을 >참고하기 바란다.
이 프로그램은 소켓을 통해서 메모리 상황을 받아서 출력만 해준다.
받은 문자열을 파싱해서 그럴듯하게 보여주는건 여러분들에게 맡기도록 하겠다.
프로그램의 실행은 가장먼저 memchecker 을 실행하고 다음 memrecevier 을 실행하고,
memsender을 실행하면 된다.
select 는 입출력다중화를 위한 목적으로 주로 쓰이며, 네트웍 프로그래밍에서 다중 클라이언트를 받아들이는 서버제작 기법으로 많이 활용된다.
예제: memsender.c
#include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #define PORT 12345 #define PACKET_SIZE 255 int main() { int fd; int n; int state; int client_len; int client_sockfd; int i; FILE *fp; char *buf; char l_buf[1]; struct sockaddr_in clientaddr; struct timeval tv; fd_set readfds; if((fd = open("/var/log/meminfo", O_RDONLY)) == -1) { perror("file open error : "); exit(0); } // memrecver 서버에 연결을 위한 소켓생성및 연결 client_sockfd = socket(AF_INET, SOCK_STREAM, 0); clientaddr.sin_family = AF_INET; clientaddr.sin_addr.s_addr = inet_addr("127.0.0.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); } fp = fdopen(fd, "w"); buf = (char *)malloc(PACKET_SIZE); i = 0; while(1) { tv.tv_sec = 0; tv.tv_usec = 10000; state = select(2, &readfds, (fd_set *)0, (fd_set *)0, &tv); switch(state) { case -1: perror("select error : "); exit(0); default : memset(buf, 0x00, PACKET_SIZE); while ((n = read(fd, l_buf, 1)) > 0) memset(buf, 0x00, PACKET_SIZE); while ((n = read(fd, l_buf, 1)) > 0) { buf[i] = l_buf[0]; if (l_buf[0] == '\n') { write(client_sockfd, buf, i+1); printf("-->%s", buf); memset(buf, 0x00, PACKET_SIZE); i = 0; continue; } i++; } break; } } close(fd); }소켓관련 프로그래밍은 셈플로 알아보는 소켓프로그래밍(1)을 >참고하기 바란다.
예제: memrecever.c
#include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #define SA struct sockaddr #define PACKET_SIZE 255 const char *needle = ": "; int main(int argc, char **argv) { int server_sockfd, client_sockfd; int state, clilen; int n; FILE *fp; struct sockaddr_in clientaddr, serveraddr; char buf_in[PACKET_SIZE]; char buf_out[PACKET_SIZE]; char *par_buf; // 소켓연결을 만든다. server_sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(12345); if(bind (server_sockfd, (SA *)&serveraddr, sizeof(serveraddr)) == -1) { perror("bind error : "); exit(0); } if ((state = listen(server_sockfd, 5)) == -1) { perror("listen error : "); exit(0); } while(1) { clilen = sizeof(clientaddr); memset(buf_in, 0x00, PACKET_SIZE); if ((client_sockfd = accept(server_sockfd, (SA *)&clientaddr, &clilen)) == -1) { perror("Accept error : "); close(client_sockfd); continue; } while(1) { if ( (n = read(client_sockfd, buf_in, PACKET_SIZE)) <= 0) { perror("read error : "); close(client_sockfd); break; } if ((par_buf = strstr(buf_in, needle)) != NULL) { printf("%s", par_buf+2); } memset(buf_in, 0x00, PACKET_SIZE); } } }받은 문자열을 파싱해서 그럴듯하게 보여주는건 여러분들에게 맡기도록 하겠다.
프로그램의 실행은 가장먼저 memchecker 을 실행하고 다음 memrecevier 을 실행하고, memsender을 실행하면 된다.
Recent Posts
Archive Posts
Tags