[Linux Socket 프로 그래 밍 입문] 04 - socket 프로 그래 밍 에서 가장 많이 사용 되 는 함수 및 데이터 구조
16608 단어 네트워크 프로 그래 밍
(1) 배경
앞의 세 마디 는 주로 socket 이 무엇 인지, 네트워크 모델, IP 주소 등 기본 적 인 지식 을 소개 하 였 으 며, 다음은 socket 프로 그래 밍 에서 가장 자주 사용 되 는 몇 가지 시스템 함수 (syscall) 와 관련 된 데이터 구 조 를 소개 하여 Liux socket 프로 그래 밍 입문 준 비 를 하 였 다.
(2) 자주 사용 하 는 데이터 구조
socket 파일 설명자 (소켓 설명자)
socket 파일 설명자 가 하나 입 니 다.
int 형식의 정수.socket 파일 설명 자 는 파일 핸들 과 유사 합 니 다. 파일 핸들 에 대한 읽 기와 쓰 기 는 파일 에 대한 읽 기와 쓰 기 를 의미 합 니 다. 마찬가지 로 socket 파일 설명 자 는 목적 정 보 를 가 진 (IP 주소, 포트 번호 등) 바이트 흐름 을 의미 합 니 다. socket 파일 설명 자 를 읽 고 쓰 는 것 은 구체 적 인 IP 주소, 포트 번 호 를 읽 고 쓰 는 것 을 의미 합 니 다. socket 파일 설명자 의 데이터 형식 은 다음 과 같 습 니 다.
int
addrinfo
이 구 조 는 socket 프로 그래 밍 을 진행 할 때 만 날 수 있 는 첫 번 째 구조 입 니 다. 주로 주소 유형, 포트 번호, socket 유형 등 매개 변 수 를 기록 하여 후속 함수 호출 을 준비 합 니 다. getaddrinfo () 의 매개 변수 입 니 다. 구 조 는 다음 과 같 습 니 다.
struct addrinfo {
int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
int ai_family; // AF_INET, AF_INET6, AF_UNSPEC
int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
int ai_protocol; // use 0 for "any"
size_t ai_addrlen; // size of ai_addr in bytes
struct sockaddr *ai_addr; // struct sockaddr_in or _in6
char *ai_canonname; // full canonical hostname
struct addrinfo *ai_next; // linked list, next node
};
그 중:
addrinfo 구조 에 sockaddr 구조 가 있 습 니 다. 이 구 조 는 주로 각종 sock address (IPv 4 or IPv 6) 정 보 를 저장 합 니 다. 그 정 의 는 다음 과 같 습 니 다.
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
그 중:sockaddr 사용 이 직관 적 이지 않 기 때문에 IPv 4 에 대해 이 구 조 를 추 가 했 습 니 다. 이 구조 체 의 내부 배열 은 sockaddr 와 같 습 니 다. 따라서 유형의 강제 전환 으로 sockaddr 를 sockaddr in 으로 강제 변환 할 수 있 습 니 다.
sock 프로 그래 밍 에 서 는 이 구조 체 를 자주 사용 하여 IP address 와 port 번 호 를 가 져 옵 니 다. 그의 정 의 는 다음 과 같 습 니 다.
struct sockaddr_in {
short int sin_family; // Address family, AF_INET
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Same size as struct sockaddr
};
그 중의 struct in addr 구 조 는 다음 과 같다.struct in_addr {
uint32_t s_addr; // that's a 32-bit int (4 bytes)
};
그 중:sockaddr in 과 마찬가지 로 이 구 조 는 주로 IPv 6 를 대상 으로 하 는데 그의 정 의 는 다음 과 같다.
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6 address
};
주의: socket 입문 에 대해 서 는 sin6 scope id 를 잠시 무시 할 수 있 습 니 다.sockaddr_storage
IPv 4 인지 IPv 6 인지 미리 알 수 없 을 때 가 있 습 니 다. IPv 4 의 정 보 를 담 을 수 있 는 구조 체 가 충분 한 지, IPv 6 의 정 보 를 담 을 수 있 는 지, 그리고 IPv 6 의 정 보 를 담 을 수 있 는 지 미리 알 수 없 을 때 가 있 습 니 다. 정 답 은: 있 습 니 다. 바로 sockaddr storage 입 니 다. 정 의 는 다음 과 같 습 니 다.
struct sockaddr_storage {
sa_family_t ss_family; // address family
// all this is padding, implementation specific, ignore it:
char __ss_pad1[_SS_PAD1SIZE];
int64_t __ss_align;
char __ss_pad2[_SS_PAD2SIZE];
};
ss family 가 AF INET 인지 AF INET 6 인지 에 따라 sockaddr storage 를 sockaddr in 또는 sockaddr in6 로 강제 변환 합 니 다. sockaddr storage 의 용법 은 다음 코드 분석 에서 볼 수 있 습 니 다.(3) 상용 함수
inet_pton()
이 함 수 는 주로 숫자 와 점 호 를 나타 내 는 IP 주 소 를 in addr 또는 in addr 6 의 구조 로 바 꾸 는 데 사 용 됩 니 다. "pton" 은 "presentation to network" 를 표시 합 니 다. 그 용법 은 다음 과 같 습 니 다.
struct sockaddr_in sa; // IPv4
struct sockaddr_in6 sa6; // IPv6
inet_pton(AF_INET, "10.12.110.57", &(sa.sin_addr)); // IPv4
inet_pton(AF_INET6, "2001:db8:63b3:1::3490", &(sa6.sin6_addr)); // IPv6
주의: 이 함수 가 실패 하면 - 1 또는 0 으로 돌아 갑 니 다. 반환 값 을 확인 하고 반환 값 이 0 이상 인지 확인 하 십시오.inet_ntop()
inet pton () 과 반대로 이 함 수 는 IP 주 소 를 숫자 와 점 으로 표시 하 는 문자열 로 변환 합 니 다. "ntop" 은 "network to presentation" 을 대표 합 니 다. 그 용법 은 다음 과 같 습 니 다.
// IPv4:
char ip4[INET_ADDRSTRLEN]; // space to hold the IPv4 string
struct sockaddr_in sa; // pretend this is loaded with something
inet_ntop(AF_INET, &(sa.sin_addr), ip4, INET_ADDRSTRLEN);
printf("The IPv4 address is: %s
", ip4);
// IPv6:
char ip6[INET6_ADDRSTRLEN]; // space to hold the IPv6 string
struct sockaddr_in6 sa6; // pretend this is loaded with something
inet_ntop(AF_INET6, &(sa6.sin6_addr), ip6, INET6_ADDRSTRLEN);
printf("The address is: %s
", ip6);
주의: INET ADDRSTRLEN 은 IPv 4 문자열 의 길 이 를 나타 내 는 미리 정 의 된 매크로 입 니 다. INET 6 ADDRSTRLEN 은 IPv 6 의 길 이 를 나타 냅 니 다.getaddrinfo()
이 함 수 는 첫 번 째 로 호출 될 함수 입 니 다. 그 역할 은 주로 필요 한 매개 변 수 를 입력 하여 시스템 이 struct addrinfo 를 자동 으로 채 워 서 후속 함수 에 사용 하도록 하 는 것 입 니 다. 함수 원형 은 다음 과 같 습 니 다.
#include
#include
#include
int getaddrinfo(const char *node, // e.g. "www.example.com" or IP
const char *service, // e.g. "http" or port number
const struct addrinfo *hints,
struct addrinfo **res);
그 중:int status;
struct addrinfo hints;
struct addrinfo *servinfo; //
memset(&hints, 0, sizeof hints); // , structure 0
hints.ai_family = AF_UNSPEC; // IPv4 IPv6, 。
hints.ai_socktype = SOCK_STREAM; // TCP socket
hints.ai_flags = AI_PASSIVE; // IP 。
if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s
", gai_strerror(status));
exit(1);
}
// servinfo , IP 。
// ...
freeaddrinfo(servinfo); // servinfo 。
socket()
이 함 수 는 주로 socket 파일 설명자 (socket file descriptor) 를 가 져 오 는 데 사 용 됩 니 다. 함수 원형 은 다음 과 같 습 니 다.
#include
#include
int socket(int domain, int type, int protocol);
그 중:int s;
struct addrinfo hints, *res;
//...
getaddrinfo("www.example.com", "http", &hints, &res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bid () 이 함 수 는 주로 포트 번 호 를 연결 하 는 데 사 용 됩 니 다. 그 원형 은 다음 과 같 습 니 다.
#include
#include
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
그 중:struct addrinfo hints, *res;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, "3490", &hints, &res);
// make a socket:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
// bind it to the port we passed in to getaddrinfo():
bind(sockfd, res->ai_addr, res->ai_addrlen);
connect () 이 함 수 는 클 라 이언 트 프로그램 에 사 용 됩 니 다. 서버 에 연결 하 는 요청 을 주동 적 으로 합 니 다. 보통 server 엔 드 의 IP 주소 와 포트 정 보 를 알 아야 합 니 다. 함수 원형 은 다음 과 같 습 니 다.
#include
#include
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
그 중:struct addrinfo hints, *res;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("www.example.com", "3490", &hints, &res);
// make a socket:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
// connect!
connect(sockfd, res->ai_addr, res->ai_addrlen);
listen()
이 함 수 는 다른 사람 에 게 당신 이 주동 적 으로 연결 (connect) 하지 않 고 다른 사람 이 당신 을 연결 할 수 있다 는 것 을 알려 주 는 데 사 용 됩 니 다. 항상 accept () 와 연 결 됩 니 다. 함수 의 원형 은 다음 과 같 습 니 다.
#include
#include
int listen(int sockfd, int backlog);
:
- sockfd:socket 。
- backlog: listen 。 accepte() , queue , queue 。
- :-1 。
Sample: , accept() 。
getaddrinfo();
socket();
bind();
listen();
/* accept() goes here */
accept()
listen 。 , blocking( sleep) (connect), , 。 :
#include
#include
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
:
- sockfd:socket 。
- addr: IP 。 , sockaddr_storage , 。
- addrlen:address , sizeof(struct sockaddr_storage) 。 , , sizeof(struct sockaddr_storage) ,addrlen 。
- :-1 。 socket 。 sockfd 。 。 ? listen , sockfd, , , 。
Sample:
#include
#include
#include
#include
#define MYPORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(void)
{
struct sockaddr_storage their_addr;
socklen_t addr_size;
struct addrinfo hints, *res;
int sockfd, new_fd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
listen(sockfd, BACKLOG);
// now accept an incoming connection:
addr_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
// ready to communicate on socket descriptor new_fd!
.
.
.
send() and recv()
。 :
int send(int sockfd, const void *msg, int len, int flags);
:
- sockfd: 。
- msg: 。
- len: 。
- flags: 0。
- :-1 。 , 。 , 。 , 1K , 。
int recv(int sockfd, void *buf, int len, int flags);
:
- sockfd: 。
- buf: buffer。
- len:buffer 。
- flags: 0。
- :-1 。0 。 byte 。
Sample: send() ,recv() 。
char *msg = "Hello World!";
int len, bytes_sent;
...
len = strlen(msg);
bytes_sent = send(sockfd, msg, len, 0);
.
.
sendto() and recvfrom()
datagram stream 。 datagram socket , UDP 。 :
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, socklen_t tolen);
:
- send() , send() 。
- to: sockaddr , IP , , , getaddrinfo() addrinfo->ai_addr。
- to_len:addr , , getaddrinfo() addrinfo->ai_addrlen。
- :-1 。 , 。 , 。
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
:
- , recv。
- from: sockaddr_storage , IP , 。
- fromlen:from 。 , , , from 。
Sample:
。
:UDP send(), recv() 。
close()
sock , close() 。 :
int close(int sockfd);
:
- sockfd
- :-1 。 0.
Sample:
...
close(fd);
--THE END--
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 네트워크 프로 그래 밍 -> 상용 모듈스 트림 소켓 을 만 들 고 지정 한 IP 주소 의 지정 한 포트 번호 에 연결 합 니 다. 이 소켓 의 입력 흐름 을 되 돌려 줍 니 다. 이 소켓 의 출력 흐름 을 되 돌려 줍 니 다. 이 IP 주소 의 호스트 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.