반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- DBMS
- 약어
- Golang
- kernel
- Preprocessor
- TiKV
- newSQL
- Programming
- 전처리기
- UNIX Internals
- 포인터변수
- Pointer
- bash
- SQLite
- getopts
- Symbol
- UNIX
- FreeBSD
- 커널
- TiDB
- 함수포인터
- 한빛미디어
- Windows via c/c++
- 컴퓨터 강좌
- 구조와 원리
- DBMS 개발
- 포인터
- OS 커널
- go
- 긴옵션
Archives
- Today
- Total
sonumb
클라이언트 연결 정보 알아내기 본문
1.개요
클라이언트가 어느 주소로 접속했는지 또한 어느 NIC로 접속했는지 서버측에서 알고 싶을 때, 아래와 같은 방법으로 이 정보를 획득한다.
- IP 주소획득은 getsockname()으로,
- NIC 이름은 getifaddrs()로
아래는 이 함수들을 이용해 실제 주소를 획득하는 예제다.
ref 정보
아래는 IPv4 이며, IPv6용이 있는지 확인해봐야 한다.
2.소스
서버는 클라이언트 접속후 단순히 클라이언트 접속 NIC의 IP와 이름을 출력하며 이를 반복한다.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
int main(int argc, char* argv[])
{
int svr_sock;
int clnt_sock;
int ret = 0;
int endconn = 0;
char buf[512];
struct sockaddr_in serv_addr;
struct sockaddr_in clint_addr;
socklen_t clnt_addr_size;
struct sockaddr_in addr[1];
socklen_t addrlen;
struct ifaddrs * ifaddr = NULL;
struct ifaddrs * ifa = NULL;
if(argc != 2)
{
printf("%s <port>\n", argv[0]);
exit(1);
}
svr_sock = socket(PF_INET, SOCK_STREAM,0); //1번
if(svr_sock == -1)
printf("socket error\n");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
if(bind(svr_sock,
(struct sockaddr*)&serv_addr,
sizeof(serv_addr)) == -1) //2번
printf("bind error\n");
if(listen(svr_sock,5)==-1) //3번
printf("listen error\n");
clnt_addr_size = sizeof(clint_addr);
label_try_accept:
clnt_sock = accept(svr_sock,
(struct sockaddr*)&clint_addr,
&clnt_addr_size); //4번
if(clnt_sock == -1)
{
printf("accept error\n");
exit(1);
}
ret = getsockname( clnt_sock,
(struct sockaddr *)addr,
&addrlen );
if( ret != 0 )
{
printf("accept error:%s\n", strerror(errno) );
exit(1);
}
getifaddrs( &ifaddr );
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
{
if (ifa->ifa_addr)
{
if (AF_INET == ifa->ifa_addr->sa_family)
{
struct sockaddr_in* inaddr = (struct sockaddr_in*)ifa->ifa_addr;
if (inaddr->sin_addr.s_addr == addr->sin_addr.s_addr)
{
if (ifa->ifa_name != NULL)
{
// Found it
strncpy(buf, inet_ntoa(addr->sin_addr), 512);
printf("sock's addr(%s), nic(%s)\n",
buf, ifa->ifa_name );
}
}
}
}
}
freeifaddrs(ifaddr);
do {
ret = recv(clnt_sock, buf, 1, 0 );
switch( ret )
{
case 1:
fputc((int)buf[0], stdout);
fflush(stdout);
break;
case 0: /* end-of-connection */
goto label_try_accept;
break;
case -1:
fprintf( stderr, "ERROR: %s\n", strerror(errno) );
endconn = 1;
break;
default:
abort();
}
} while ( endconn == 0 );
close(svr_sock); //6번
close(clnt_sock);
return 0;
}
client.c
#include<stdio.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
int main(int argc, char* argv[])
{
int my_sock;
struct sockaddr_in serv_addr;
int str_len;
if(argc != 3)
{
printf("%s <IP> <PORT>\n", argv[0]);
exit(1);
}
my_sock = socket(PF_INET,SOCK_STREAM,0); //1번
if(my_sock == -1)
printf("socket error \n");
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr =
inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if(connect(my_sock,
(struct sockaddr*)&serv_addr,
sizeof(serv_addr))==-1) //2번
printf("connect error\n");
close(my_sock); //4번
return 0;
}
3.실행 결과
server
$ ./server 6600
sock's addr(192.168.19.135), nic(ens33)
sock's addr(127.0.0.1), nic(lo)
client
$ ./client 192.168.19.135 6600
$ ./client 127.0.0.1 6600
$
반응형