int server_socket;
int client_socket;
int client_addr_size;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
char buff_rcv[BUFF_SIZE+5];
char buff_snd[BUFF_SIZE+5];
1. int socket(int domain, int type, int protocol);
domain
- PF_INET, AF_INET : IPv4인터넷 프로토콜을 사용
- PF_INET6 : IPv6인터넷 프로토콜을 사용
- PF_LOCAL, AF_UNIX : 같으 시스템 내에서 프로세스끼리 통신합니다.
- PF_PACKET : Low level socket 을 인터페이스를 이용
- PF_IPX : IPX 노벨 프로토콜을 사용
type
- SOCK_STREAM : TCP/IP 프로토콜을 이용
- SOCK_DGRAM : UDP/IP 프로토콜을 이용
protocol : 통신에 있어 특정 프로토콜을 사용을 지정하기 위한 변수 ,보통 0값을 사용
성공 시 파일 디스크립터, 실패 시 -1 반환
server_socket = socket( PF_INET, SOCK_STREAM, 0);
if( -1 == server_socket)
{
printf( "server socket 생성 실패\n");
exit( 1);
}
2. int bind(int sockfd,(struct sockaddr *)&myaddr, socklen_t addrlen);
- sockfd : 소켓 디스크립터
- sockaddr *myaddr : 주소 정보로 인터넷을 이용하는 AF_INET인지 시스템 내에서 통신하는 AF_UNIX에 따라서 달라집니다.
인터넷을 통해 통신하는 AF_INET인 경우에는 struct sockaddr_in을 사용합니다.
- socklen_t addrlen : myadd 구조체의 크기 ex) size(sock_addr)
성공 시 0 , 실패 시 -1 반환
if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
{
printf( "bind() 실행 에러\n");
exit( 1);
}
주소정보의 표현 (sockaddr/ sockaddr_in)
- sockaddr : 소켓주소를 표현하는 구조체
TCP/IP만을 목적으로 만들어진 것이 아니기 때문에, 다양한 주소체계에 맞게 범용 목적으로 사용하기 위해이런 단순한 구조를 가지고있다.
struct sockaddr{
sa_family_t sa_family ; 소켓 주소체계
char sa_data[4]; 해당 주소체계에서 사용하는 주소정보
- sockaddr_in : IPv4 주소체계에서 사용하는 구조체
소켓 프로그램은 범용 주소 구조체로 sockaddr을 사용하지만, 주소체계의 종류에 따라 별도의 전용 구조체를 만들어 사용하는게 편리하다.
struct sockaddr_in {
sin_family_t sin_family; IPv4주소 체계에서 사용하므로 항상 AF_INET으로 설정
unist16_t sin_port; 포트번호
struct in_addr sin_addr; IP주소를 나타내는 32비트 정수 타입구조체
char sin_zero[8]; sockaddr과 같은 크기를 유지하기 위해 필요한 패딩공간. 항상 0
struct in_addr {
unit32_t s_addr; 32비트 IPv4 인터넷 주소
}
sin_family : 주소체계(AF_INET / AF_INET6 / AF_LOCAL)
sin_port : 16비트 포트정보
sin_addr : 32비트 IP정보
sin_zero : 사용되지 않는 필드
3. int listen(int sockfd, int backlog);
- sockfd : 소켓 디스크립터
- backlog : 대기 메시지 큐의 개수
성공시 0, 실패 시 -1 반환
if( -1 == listen(server_socket, 5))
{
printf( "listen() 실행 실패\n");
exit( 1);
}
4. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- sockfd : 소켓 디스크립터
- sockaddr *addr : 클라이언트 주소정보를 가지고 있는 포인터
- socklen_t addrlen : struct sockaddr *addr 포인터가 가르키는 구조체의 크기
성공 시 파일 디스크립터, 실패 시 -1 반환
while( 1)
{
client_addr_size = sizeof( client_addr);
client_socket = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
if ( -1 == client_socket)
{
printf( "클라이언트 연결 수락 실패\n");
exit( 1);
}
5. int connect(int sockfd,struct sockaddr * serv_addr, socklen_t addrlen);
- sockfd : 소켓 디스크립터
- sockaddr *serv_addr : 서버 주소 정보에 대한 포인터
- socklen_t addrlen : struct sockaddr *serv_addr 포인터 가르키는 구조체의 크기
성공시 0, 실패 시 -1 반환
if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
{
printf( "접속 실패\n");
exit( 1);
}
TCP/IP 통신 함수 사용순서
서버프로그램 예제
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define BUFF_SIZE 1024
int main( void)
{
int server_socket;
int client_socket;
int client_addr_size;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
char buff_rcv[BUFF_SIZE+5];
char buff_snd[BUFF_SIZE+5];
server_socket = socket( PF_INET, SOCK_STREAM, 0);
if( -1 == server_socket)
{
printf( "server socket 생성 실패\n");
exit( 1);
}
memset( &server_addr, 0, sizeof( server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( 4000);
server_addr.sin_addr.s_addr= htonl( INADDR_ANY);
if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
{
printf( "bind() 실행 에러\n");
exit( 1);
}
if( -1 == listen(server_socket, 5))
{
printf( "listen() 실행 실패\n");
exit( 1);
}
while( 1)
{
client_addr_size = sizeof( client_addr);
client_socket = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
if ( -1 == client_socket)
{
printf( "클라이언트 연결 수락 실패\n");
exit( 1);
}
read ( client_socket, buff_rcv, BUFF_SIZE);
printf( "receive: %s\n", buff_rcv);
sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
write( client_socket, buff_snd, strlen( buff_snd)+1); // +1: NULL까지 포함해서 전송
close( client_socket);
}
}
클라이언트 프로그램 예제
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define BUFF_SIZE 1024
int main( int argc, char **argv)
{
int client_socket;
struct sockaddr_in server_addr;
char buff[BUFF_SIZE+5];
client_socket = socket( PF_INET, SOCK_STREAM, 0);
if( -1 == client_socket)
{
printf( "socket 생성 실패\n");
exit( 1);
}
memset( &server_addr, 0, sizeof( server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( 4000);
server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");
if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
{
printf( "접속 실패\n");
exit( 1);
}
write( client_socket, argv[1], strlen( argv[1])+1); // +1: NULL까지 포함해서 전송
read ( client_socket, buff, BUFF_SIZE);
printf( "%s\n", buff);
close( client_socket);
return 0;
}