오늘은 TCP 소켓 프로그래밍에 대해서 포스팅을 하겠습니다.
일단, 네트워크는 5계층으로 나뉩니다.
(7계층도 있지만, 간략하게 5계층으로 설명하겠습니다.)
[ 네트워크 5계층 ]
[ TCP/IP 배경지식 ]
두 프로그램이 네트워크를 통해 서로 통신을 수행 할 수 있도록 양쪽에 생성되는 링크의 단자입니다. 두 소켓이 연결되면 서로 다른 프로세스끼리 데이터를 전달 할 수 있습니다.
[ TCP 소켓 프로그래밍 ]
클라이언트단에서 사용하는 기본 함수
socket -> connect -> send -> recv -> close
int socket(int protocolFamily, int type, int protocol)
PF_INET : SOCK_STREAM or SOCK_DGRAM : IPPROTO_TCP or IPPROTO_UDP or 0(defulat)
0 : socket descriptor(음이 아닌 값), connect, recv, send, close에 모두 사용됨
-1 : 실패
[Example]
client_socket = socket( PF_INET, SOCK_STREAM, 0);
if (client_socket == -1)
{
printf( "create socket failed\n");
return -1;
}
int close(int socket)
0 : 성공
-1 : 실패
소켓을 모두 사용하고 자원정리 할 때 사용되는 함수
int connect(int socket, struct sockaddr *foreignAddress, unsigned int addressLength)
socket api return 값, 아래의 코드블럭의 주소 구조체에 채워져 있는 주소값, 주소 구조체의 길이
[Example]
while ( connect( client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr) ) == -1 )
{
if (fail_cnt <= 10)
{
sleep(1);
fail_cnt++;
}
else
{
printf("connection failed..");
return -1;
}
}
int send(int socket, const void *msg, unsigned int msgLength, int flags)
int recv(int socket, void *recvBuffer, unsigned int bufferLength, int flags)
성공 시 send 한 byte length, 실패 시 -1
성공 시 recv 한 byte length, 실패 시 -1
소켓 프로그래밍에 사용되는 구조체
struct sockaddr
{
unsigned short sa_familty; /* Address familty(e.g. AF_INET) */
char sa_data[14]; /* Family-specific address information */
}
struct in_addr
{
unsigned long s_addr; /* Internet Address 32 bits */
}
struct sockaddr_in
{
unsigned short sin_familty; /* Internet Protocol (AF_INET) */
unsigned short sin_port; /* Address Port 16 bits */
struct in_addr sin_addr; /* Internet Address 32 bits */
char sin_zero[8]; /* Not used */
}
[ 예제 프로그램 ]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT 1004
#define IPADDR "127.0.0.1" // Loopback 주소, 자기 자신 주소
#define BUFFER_SIZE 4096
void main()
{
int socket_fd = -1;
struct sockaddr_in c_addr;
char send_buffer[BUFFER_SIZE], recv_buffer[BUFFER_SIZE];
socket_fd = socket(PF_INET, SOCK_STREAM, 0); // SOCK_STREAM : TCP
memset(&c_addr, 0, sizeof(c_addr));
c_addr.sin_addr.s_addr = inet_addr(IPADDR); // IP 주소
c_addr.sin_family = AF_INET; // IPv4 설정
c_addr.sin_port = htons(PORT); // PORT 설정
if(connect(socket_fd, (struct sockaddr *)&c_addr, sizeof(c_addr)) == -1 )
{
// 실패 예외처리
close(socket_fd);
}
while(1)
{
// 원하는 메세지 send
n_send = send(socket_fd, send_buffer, BUFFER_SIZE);
// 서버단에서 메세지 recv
n_recv = read(socket_fd, recv_buffer, BUFFER_SIZE);
if ( 조건문 )
{
// 종료 조건
break;
}
}
if ( socket_fd > 0 )
{
// 소켓 종료
close(socket_fd);
}
}
위에 처럼 간단하게 프로그래밍을 할 수 있습니다.
클라이언트는 물론 서버와 통신 프로그램과 같이 해야 정상적으로 작동합니다.
connect 단계에서 서버가 작동하고 있지 않으면 에러가 나면서 종료됩니다.
이상 간단한 클라이언트 프로그램이였습니다.
다음번엔 서버 프로그래밍에 대해서 포스팅 하겠습니다.
그럼 20000.
네트워크 UPnP 정리, Discovery 방법, SSDP (2) | 2020.06.04 |
---|---|
TCP/IP, UDP, 네트워크 통신 (4) | 2020.04.03 |
Samba 서버 설정, 쌈바 서버 설정, Ubuntu, 우분트 서버, 리눅스 서버 (0) | 2020.03.07 |
HTTP 인증, Baisic 인증, Digest 인증, 네트워크 보안 (0) | 2020.03.06 |
네트워크 장비, 허브(Hub), 스위치(Switch), 라우터(Router) 개념 및 정리 (0) | 2020.03.05 |