/*
* http://sosal.tistory.com/
* made by so_Sal
*/
서버 소켓 함수들
#include<sys/socket.h>
int socket( int __domain, int __type, int __protocol);
int bind(int socket, const struct sockaddr *address, size_t address_len);
int listen(int socket, int backlog);
int accept(int socket,struct sockaddr *address, size_t address_len);
int connect(int socket, const struct sockaddr *address, size_t address_len);
:: socket :: linux programing 소켓의 첫 글을 참조하세요.
:: bind :: // 소켓에 이름 붙이기.
int bind(int socket, const struct sockaddr *address, size_t address_len);
//소켓 //주소 //주소의 길이
socket을 다른 프로세스들이 사용 할 수 있게 하려면,
소켓에 정보들이 있어야 합니다.
마치 집에서 다른집으로 전화를 할때 전화번호를 알아야 전화할 수 있는것 처럼.
AF_UNIX :: 유닉스 내부 네트워크 시스템 소켓 :: 주소가 곧 *경로*
AF_INET :: 유닉스 외부 네트워크 시스템 소켓 :: IP, Port가 주소이다.
내부 네트워크 AF_UNIX 도메인 에서는, 소켓의 위치를 알아야 통신이 가능합니다.
(서버에서 만든 소켓이 프로세들의 통신을 가능하게 해줌.)
외부 인터넷 네트워크 AF_INET 도메인 에서는,
학교의 이름(IP)과 반의 위치(port)를 알아야 반에 찾아갈 수 있겠죠.
bind :: 소켓과 주소를 합치는 함수
소켓 1번글 01. socket(), sockaddr 에 대한 글에서 sockaddr을 참조하세요.
socket()로 생성한 소켓과 sockaddr 구조체를 합쳐주는 역할을 하는것이 bind()
소켓에 주소를 연결 한다면, 클라이언트 프로세스가 소켓을 찾아갈 수 있을 것.
물론 이때의 소켓은 서버 소켓이고, 주소 역시 서버소켓의 구조체입니다.
:: listen :: // 소켓의 귓구멍을 열어놓기
int listen(int socket, int backlog);
//소켓 //소켓 연결요청 대기열
일단 누구와 이야기 하기 위해선 귀가 있어야 함.
listen 함수가 귀를 여는 역할을 한다.
전화를 예로 들자면, 전화선을 꼽는것.
소켓 연결요청 대기열은 접속 연결시도가 들어올 수 있는 최대 갯수를 말한다.
보통 5를 많이 사용함..
:: accept :: // 상대가 말을 걸면 대화를 받아줌
listen 함수에서 귀를 뚫었다면, 나에게 대화를 건 상대를 받아 주기만 하면 되겠다.
누군가가 전화를 걸면 받는 행위라고 생각하면 될듯 합니다.
하지만 대화를 거는 상대가 없다면, 기다려야겠지요?
이 함수는 상대방이 연결을 시도할 것을 기다립니다.
accept에서 2번째 인자 sockaddr은 상대방의 주소를 나타내는 구조체입니다.
상대방이 내 소켓에 연결하여 던져준 내용이
누가 줬는지 기억해야만 답장을 보낼 수 있겠지요..!?
accept 함수는 연결요청이 있다면, 프로세스의 실행이 재개되고,
그 소켓 연결 요청을 수락했을때, 소켓 서술자를 반환하게 됩니다.
소켓 연결 대기열 backlog에 연결 요청이 하나도 없다면 호출이 차단됩니다.
위 차단 특성은 O_NONBLOCK 플래그를 설정함으로 써 변경 할 수 있습니다.
fcnt 계열의 함수를 사용.
int falgs = fcntl(socket, F_GETFL, 0);
fcntl(socket, F_SETFL, O_NONBLOCK | flags);
자세한 fcntl에 대한 내용은 생략하겠습니다. ㅠㅠ
예제); 아래 예제는 바로 다음 client socket 글의 예제와 연결되는 예제입니다.
물론 AF_UNIX도메인과 AF_INET 도메인으로 따로 나뉘어 집니다.
모두 내부에서 소켓을 이용하여 통신하는 프로그램들 이지만,
인터넷 프로토콜 AF_INET 또한 내부에서 통신이 가능하므로
둘다 예제를 실험해 보세요~~^-^
====== AF_INET 외부 인터넷 네트워크 도메인 server.c =======
/* 열혈강의 윤성우저자의 소스입니다.
* helloworld_server.c
* Written by SW. YOON
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
void error_handling(char *message);
int main(int argc, char *argv[])
{
int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in clnt_addr;
int clnt_addr_size;
char message[]="Hello World!\n";
if(argc!=2){
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0); /* 서버 소켓 생성 */
if(serv_sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(atoi(argv[1]));
if( bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1 ) /* 소켓에 주소 할당 */
error_handling("bind() error");
if( listen(serv_sock, 5)==-1 ) /* 연결 요청 대기 상태로 진입 */
error_handling("listen() error");
clnt_addr_size=sizeof(clnt_addr);
clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size); /* 연결 요청 수락 */
if(clnt_sock==-1)
error_handling("accept() error");
write(clnt_sock, message, sizeof(message)); /* 데이터 전송 */
close(clnt_sock); /* 연결 종료 */
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
===== AF_UNIX 내부 네트워크 도메인 server.c =====
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
int main(){
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address;
struct sockaddr_un client_address;
unlink("server_socket");
//현재 위치에 server_socket이라는 파일을 만드는데,
//그와 똑같은 이름이 있다면 없애야겠습니다. 그 함수입니다.
server_sockfd = socket(AF_UNIX, SOCK_STREAM,0);
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "01.server_socket");
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
//주소구조체를 만들어서 소켓과 합침으로써 소켓에 주소가 생겼습니다.
listen(server_sockfd, 5);
//전화를 받을 수 있는 상태를 만드는 listen입니다. 아래 accept에서 기다리겠지요.
while(1){
char ch;
printf("server waiting \n");
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address,&client_len);
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}
Socket 게시물들은
begining Linux programing.
Linux 언쉬리드' 를 참고하였습니다.
'Linux > Linux_programing' 카테고리의 다른 글
System - 01. Process 개념 (0) | 2009.10.07 |
---|---|
Socket - 03. Client socket (2) | 2009.10.03 |
리눅스 Socket - socket(), sockaddr (0) | 2009.09.28 |
리눅스 FILE - open(), close() 시스템콜 (1) | 2009.09.28 |
리눅스 FILE - read() 시스템콜 (1) | 2009.09.27 |