linux echo server ( pthread 사용 )프로그래밍 노트/C&C++2015. 11. 14. 09:53
Table of Contents
반응형
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/wait.h>
- #include <pthread.h>
- #include <signal.h>
- struct thread_data{
- int fd;
- char ip[20];
- };
- void *ThreadMain(void *argument);
- // get sockaddr, IPv4 or IPv6:
- void *get_in_addr(struct sockaddr *sa)
- {
- if (sa->sa_family == AF_INET) {
- return &(((struct sockaddr_in*)sa)->sin_addr);
- }
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
- }
- int main(void)
- {
- int sockfd, new_fd;
- struct sockaddr_storage client_addr;
- struct sockaddr_in servaddr;
- socklen_t sin_size;
- char address[20];
- int ret;
- pthread_t thread_id;
- //이미 연결이 종료된 클라이언트에 Send하려고 했을따 나오는 시그널을
- //처리해주지 않으면 기본 동작은 프로그램 종료라서 서버가 다운된다.
- //클라이언트가 비정상적인 종료를 했을때 broken pipe signal이 발생하고
- //클라이언트 종료를 서버에서 제어할수 없기때문에 해당 시그널을 무시
- //하도록 해주어야 한다.
- //http://egloos.zum.com/nomoreid/v/1169779
- signal( SIGPIPE, SIG_IGN );
- sockfd = socket(AF_INET, SOCK_STREAM,0);
- bzero( &servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = INADDR_ANY;
- unsigned int port = 9999;
- servaddr.sin_port = htons(port);
- ret = bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
- if ( ret != 0 )
- {
- perror("bind");
- exit(-1);
- }
- ret = listen(sockfd, 5);
- if ( ret != 0 )
- {
- perror("listen");
- exit(-1);
- }
- while(1) { // main accept() loop
- printf( "i am wait new client \n" );
- sin_size = sizeof client_addr;
- new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
- if (new_fd == -1) {
- perror("accept");
- continue;
- }
- inet_ntop(client_addr.ss_family,
- get_in_addr((struct sockaddr *)&client_addr),
- address, sizeof address);
- printf("server: got connection from %s\n", address);
- struct thread_data *data;
- data= (struct thread_data*)malloc(sizeof(struct thread_data));
- data->fd = new_fd;
- strcpy( data->ip,address);
- pthread_create( &thread_id, NULL, ThreadMain, (void*)data);
- }
- return 0;
- }
- void *ThreadMain(void *argument)
- {
- struct thread_data *client_data;
- char buf[1024];
- pthread_detach(pthread_self());
- client_data = (struct thread_data*)argument;
- int fd = client_data->fd;
- char ip[20];
- strcpy( ip, client_data->ip);
- while(1)
- {
- int num;
- num = read( fd, buf, sizeof(buf) );
- //클라이언트가 갑자기 끊어버리면 read함수는 0을 리턴한다.
- if ( num == 0 ) break;
- printf("recv : [%s] %dbyte\n", buf, num );
- write( fd, buf, strlen(buf));
- }
- printf("disconnected client ip %s\n", ip );
- free(client_data);
- close(client_data->fd);
- return 0;
- }
참고
https://computing.llnl.gov/tutorials/pthreads/
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Thread/Beginning/Example_pthread
http://egloos.zum.com/nomoreid/v/1169779
http://beej.us/guide/bgnet/output/html/multipage/index.html
반응형
'프로그래밍 노트 > C&C++' 카테고리의 다른 글
C++ shared_ptr 예제, 사용방법 (0) | 2021.01.01 |
---|---|
C++ localtime 사용하여 현재 날짜, 시간 출력하기 (Windows/Linux) (0) | 2020.12.11 |
C++ - 터미널의 특정 위치에 문자열 출력하기 (0) | 2020.12.10 |
C++ 클래스에서 static 멤버변수 초기화 (0) | 2020.09.01 |
디렉토리에서 특정 문자열로 시작하는 엔트리 읽어오기 (0) | 2015.01.22 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
@webnautes :: 멈춤보단 천천히라도
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!