소켓옵션

System Program/socket 2014. 3. 5. 10:23

1. 소개

 

소켓을 이용해서 프로그램을 개발할 때, 일반적인 소켓 API를 구성하여 작성하는 기본적인 구현 이외에

소켓 설정에 대한 수정을 통해서 더 정교한 제어를 할 수 있다.

소켓 설정에 대한 수정은 소켓 옵션 설정 시스템 함수를 통하여 이루어진다.

 

2. 소켓 옵션 함수

 

#include <sys/socket.h>

 

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

 

성공하면 '0'을 리턴하고, 에러가 발생하면 '-1'을 리턴 

 

위의 함수에서 다른 매개변수은 쉽게 이해할 수 있다.

두번째 매개변수인 level에 대해서 정리하면 아래와 같다.

 

 level

설명 

참고문서 

 SOL_SOCKET

 socket() 함수 레벨에서 옵션 수정

 socket (7) manual 참조 

 IPPROTO_TCP

 TCP 소켓에 대한 옵션 수정 

 tcp (7) manual 참조 

 IPPROTO_UDP

 UDP 소켓에 대한 옵션 수정 

 udp (7) manual 참조 

 IPPROTO_IP

 IP 단계에 대한 옵션 수정  

 ip (7) manual 참조 

 

세번째 인자에 대한 가능한 optname은 참고문서에서 기술한 메뉴얼을 참조

 

3. 예시

 

완전한 예시라기 보다는 옵션 함수 사용법 정도 본다는 수준이다.

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main(int argc, char *argv[])
{
	static int reuseflag = 1;
	size_t sockbuffer = (188 * 7) * 150;
	socklen_t sockbufferlen = 0;
	int sockfd;
	struct sockaddr_in server_addr;

	sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(sockfd < 0)
	{
		perror("socket : ");
		exit(EXIT_FAILURE);
	}
	
	/* 연결 중에 잠시 발생한 에러로 연결해제된 주소에 대해 기존 kernel이 유지 중인 주소를 재 사용 */
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuseflag, (socklen_t)sizeof(reuseflag)) != 0)
	{
		perror("setsockopt : ");
		exit(EXIT_FAILURE);		
	}	

	/* socket buffer 수정 */
	if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sockbuffer, sizeof(sockbuffer)) != 0)
	{
		perror("setsockopt : ");
		exit(EXIT_FAILURE);		
	}	

	if(getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sockbuffer, &sockbufferlen) != 0)
	{
		perror("setsockopt : ");
		exit(EXIT_FAILURE);		
	}

	printf("socket buffer size = %d\n", sockbuffer); 
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(5000);
	
	if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
	{
		perror("bind : ");
		exit(EXIT_FAILURE);			
	}
	
	return 0;
}


 

 

 

 

 

 

: