티스토리 뷰
socket으로 기본적인 서버 프로그램을 만들어보자.
프로그램은 하나의 클라이언트를 처리하며, 받은 데이터를 다시 클라이언트에게 전달하는 echo기능을 수행한다.
#include <socket.h>
#include <stat.h>
#include <inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main(){
int server_socket, client_socket;
int client_len, n;
char buf[BUF_SIZE];
struct sockaddr_in client_addr, server_addr;
client_len = sizeof(client_addr);
// 소켓을 생성한다.
if((server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) == -1){
printf("socket error\n");
return 0;
}
// 서버의 ip주소와 port번호를 sockaddr_in 구조체에 저장한다.
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(3500);
// 구조체에 저장한 주소를 socket에 연결한다.
bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 클라이언트의 연결을 기다린다.
listen(server_socket, 5);
// 반복
while(1){
memset(buf, 0, BUF_SIZE);
// 클라이언트의 연결을 수락한다.
client_socket = accept(server_socket, (struct sockaddr*)&client_addr, sizeof(client_len));
printf("new client : %s\n", inet_ntoa(client_addr.sin_addr));
// 클라이언트로부터 전달받은 데이터를 읽는다.
if((n = read(client_socket, buf, BUF_SIZE) <= 0){
close(client_socket);
continue;
}
// 전달받은 데이터를 다시 전송한다.
if(write(client_socket, buf, BUF_SIZE) <= 0){
printf("write error\n");
close(client_socket);
}
// 클라이언트 소켓을 종료한다.
close(client_socket);
}
// 서버 소켓을 종료한다.
close(server_socket);
return 0;
}
서버 프로그램의 흐름인 socket() - bind() - listen() - accept() - read()/write() - close() 함수를 중점적으로 코드를 다시 보자.
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
IPv4를 사용하며(AF_INET), TCP/IP 프로토콜을 사용하는(SOCK_STREAM/IPPROTO_TCP) socket을 생성했다. 생성된 socket은 아직 주소와 포트와 연결되지 않았다.
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(3500);
bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
먼저 서버의 ip주소와 port번호를 sockaddr_in구조체에 채운다. sockaddr_in구조체는 ip주소와 port번호를 맴버로 가지고 있는 구조체이다.
* 네트워크 통신을 할 때 주의해야 할 점은 네트워크 바이트 순서와 일반 컴퓨터의 바이트 순서가 다르다는 것인데 hton*() ntoh*() 함수로 네크워크 바이트로 데이터를 변환해서 통신해야 한다. 자세한 내용은 (글 링크)
listen(server_socket, 5);
server_socket으로 들어오는 클라이언트의 요청을 최대 5개 까지 기다린다. 보통 5 값을 사용한다.
client_socket = accept(server_socket, (struct sockaddr*)&client_addr, sizeof(client_len));
server_socket으로 연결 요청이 온 클라이언트 소켓을 받아들인다. 클라이언트 소켓의 소켓번호가 반환되고, client_addr 구조체에 클라이언트의 ip주소, port번호가 저장된다.
n = read(client_socket, buf, BUF_SIZE)
클라이언트 소켓으로부터 데이터를 읽어온다. 반환되는 값은 읽은 데이터의 길이로 0이하의 값이 반환되면 데이터를 읽지 않았다는 뜻으로 이 프로그램에서는 소켓을 종료한다.
write(client_socket, buf, BUF_SIZE)
클라이언트 소켓에 buf데이터를 쓴다. 반환되는 값은 실제로 쓴 데이터의 크기이다. 0이하의 값이 반환되면 쓰기에 문제가 생겼다는 뜻으로 소켓을 종료한다.
close(client_socket);
close(server_socket);
소켓을 종료한다.
'Programming > Socket' 카테고리의 다른 글
socket으로 네트워크 엔진 만들기 (2) - socket 생성 (0) | 2017.07.13 |
---|---|
socket으로 네트워크 엔진 만들기 (1) - Packet class 정의 (0) | 2017.07.11 |
socket : socket() (0) | 2017.02.02 |
socket : socket이란? (0) | 2017.01.30 |
socket : TCP/IP란? (0) | 2017.01.30 |
- Total
- Today
- Yesterday
- C++
- JSP
- machine learing
- SwiftUI
- OS
- swift
- Spring
- 알고리즘
- 국내여행
- ue4
- Git
- SOCKET
- database
- ios
- Cocos2d-x
- 운영체제
- scala
- winsock
- SHADER
- 수학
- 자료구조
- 드라마
- C
- game
- C/C++
- DesignPattern
- Java
- mongoDB
- 데이터베이스
- rxswift
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |