- Socket은 커널에 구현된 프로토콜 요소의 추상화된 인터페이스
- 장치 파일의 일종
- 연결을 끊을 때는 Client가 끊도록 하는 것이 바람직
전체 흐름
Server(서버 소켓 + 통신 소켓)
socket() : 소켓 생성
bind() : ip 주소 및 포트를 socket에 묶음(binding)
listen() : client로부터의 연결을 대기
accept() : client로부터의 연결 요청에 응답
recv() / send() : 데이터 송수신
Client(통신 소켓)
socket() : 소켓 생성
connect() : server로 연결 요청
recv() / send() : 데이터 송수신
API
Socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- domain
- AF_UNIX
- AF_LOCAL
- AF_INET : ipv4
- AF_INET6 : ipv6
- type
- SOCK_STREAM : tcp
- SOCK_DGRAM : udp
- protocol
- return
- -1 : error
- 0 : success
Bind
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- sockfd : 소켓 식별자 또는 디스크립터(서버)
- addr : ip 정보가 담겨있는 구조체
- addrlen : 구조체 크기
- return
- 0 : success
- -1 : error
Listen
#include <sys/socket.h>
int listen(int sock, int backlog);
- sock : 대기 상태에 두고자 하는 소켓 식별자 또는 디스크립터(서버)
- backlog : 연결요청 대기 큐(queue)의 크기
- return
- 0 : success
- -1 : error
Accept
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, sockelnt_t *addrlen);
- sockfd : 서버
- addr : 클라이언트 ip 정보가 담긴 구조체
- addrlen : 구조체 크기
- return
- -1 : error
- 나머지 : 서버에서 통신할 소켓 디스크립터
Connect
#include <sys/types.h>
#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address, socklent_t address_len);
- socket : 클라이언트
- address : 서버의 주소 정보가 담긴 구조체
- address_len : 구조체 크기
- return
- -1 : error
- 0 : success
Send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
- sockfd : 통신할 소켓 디스크립터
- buf : 보낼 메세지가 담긴 버퍼
- len : buffer의 크기
- flags : 전송 옵션
- return
- -1 : error
- 나머지 : 보낸 바이트 크기
Recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void* buf, size_t len, int flags);
- sockfd : 통신할 소켓 디스크립터
- buf : 받은 메세지를 담을 버퍼
- len : 받아올 크기
- flags : 수신 옵션
- return
- -1 : error
- 나머지 : 받은 바이트 크기
Example
Server
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <pthread.h>
#include <signal.h>
#define BUFF_SIZE 1024
#define FILE_PATH "./test"
#define Error() perror("Error: ");\
return -1;
void* send_msg(void* c_fd) {
char s_buff[BUFF_SIZE];
while (1)
{
printf("You: ");
fgets(s_buff, BUFF_SIZE, stdin);
if (!write(*(int*)c_fd, s_buff, BUFF_SIZE))
{
perror("Error: send message");
}
}
}
int main(void) {
int s_fd, c_fd, c_addr_size;
struct sockaddr_un s_addr, c_addr;
char c_buff[BUFF_SIZE];
sigset_t sigset;
pthread_t send_thread;
if (!access(FILE_PATH, F_OK))
unlink(FILE_PATH);
s_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s_fd == -1)
{
Error();
}
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, FILE_PATH);
if (bind(s_fd, (struct sockaddr*)&s_addr, sizeof(s_addr)) == -1)
{
close(s_fd);
Error();
}
if (listen(s_fd, 5) == -1)
{
close(s_fd);
Error();
}
printf("Listening...\n");
c_addr_size = sizeof(c_addr);
c_fd = accept(s_fd, (struct sockaddr*)&c_addr, &c_addr_size);
if (c_fd == -1)
{
close(s_fd);
Error();
}
printf("Accept!\n");
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_BLOCK, &sigset, (sigset_t*)NULL);
pthread_create(&send_thread, NULL, send_msg, (void*)&c_fd);
while (read(c_fd, c_buff, BUFF_SIZE))
{
printf("\nClient said : %s", c_buff);
if (!strcmp(c_buff, "bye\n"))
break;
}
if (shutdown(c_fd, SHUT_RDWR) == -1)
{
Error();
}
close(c_fd);
close(s_fd);
}
Client
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pthread.h>
#define BUFF_SIZE 1024
#define FILE_PATH "./test"
#define Error() perror("Error: ");\
return -1;
void* read_msg(void* c_fd) {
char s_buff[BUFF_SIZE];
while (1)
{
read(*(int*)c_fd, s_buff, BUFF_SIZE);
printf("\nServer said: %s", s_buff);
}
}
int main(void) {
int c_fd;
struct sockaddr_un s_addr;
char c_buff[BUFF_SIZE];
pthread_t read_thread;
c_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (c_fd == -1)
{
Error();
}
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, FILE_PATH);
if (connect(c_fd, (struct sockaddr*)&s_addr, sizeof(s_addr)) == -1)
{
close(c_fd);
Error();
}
puts("Connected!");
pthread_create(&read_thread, NULL, read_msg, (void*)&c_fd);
while (1)
{
printf("You: ");
fgets(c_buff, BUFF_SIZE, stdin);
if (!write(c_fd, c_buff, BUFF_SIZE))
{
perror("Error: send message");
}
if (!strcmp(c_buff, "bye\n")) break;
}
if (shutdown(c_fd, SHUT_RDWR) == -1)
{
Error();
}
close(c_fd);
}
'💻 Computer Science > System' 카테고리의 다른 글
[System] Semaphore (1) | 2024.01.26 |
---|---|
[System] Shared Memory (1) | 2024.01.26 |
[System] Named Pipe (1) | 2024.01.26 |
[System] 메모리 맵핑 (1) | 2024.01.26 |
[System] 시그널 (1) | 2024.01.25 |