getsockname与getpeername
int getsockname(int sockfd, struct sockaddr * localaddr, socken_t * addrlen);
int getpeername(int sockfd, struct sockaddr * peeraddr, socken_t * addrlen);
返回0表示成功,返回1表示出錯
參數sockfd表示你要獲取的套接口的描述字。
localaddr返回本地協議地址描述結構, peeraddr返回遠程協議地址描述結構,addrlen分別是上述2個結構的長度。這個2個函數不難,下面是使用樣例
#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char ** argu) {
int listenfd;
struct sockaddr_in servaddr;
pid_t pid;
char temp[100];
int n = 0;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(atoi(argu[1]));
bind(listenfd, (struct socket_addr *)&servaddr, sizeof(servaddr));
listen(listenfd, n);
for(;;) {
struct sockaddr_in local;
int connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
if((pid = fork()) == 0) {
struct sockaddr_in serv, guest;
char serv_ip[20];
char guest_ip[20];
int serv_len = sizeof(serv);
int guest_len = sizeof(guest);
getsockname(connfd, (struct sockaddr *)&serv, &serv_len);
getpeername(connfd, (struct sockaddr *)&guest, &guest_len);
inet_ntop(AF_INET, &serv.sin_addr, serv_ip, sizeof(serv_ip));
inet_ntop(AF_INET, &guest.sin_addr, guest_ip, sizeof(guest_ip));
printf("host %s:%d guest %s:%d\n", serv_ip, ntohs(serv.sin_port), guest_ip, ntohs(guest.sin_port));
char buf[] = "hello world";
write(connfd, buf, strlen(buf));
close(connfd);
exit(0);
}
close(connfd);
}
}
[root@liumengli net]# cat client1.c
#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char ** argv) {
int sockfd, n;
int my;
char buf[100];
struct sockaddr_in servaddr;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("create socket error\n");
exit(1);
}
bzero(&servaddr, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
printf("inet_pton error\n");
exit(1);
}
if((my = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0) {
printf("connect error\n");
exit(1);
}
struct sockaddr_in serv, guest;
int serv_len = sizeof(serv);
int guest_len = sizeof(guest);
char serv_ip[20], guest_ip[20];
getsockname(sockfd, (struct sockaddr *)&guest, &guest_len);
getpeername(sockfd, (struct sockaddr *)&serv, &serv_len);
inet_ntop(AF_INET, &guest.sin_addr, guest_ip, sizeof(guest_ip));
inet_ntop(AF_INET, &serv.sin_addr, serv_ip, sizeof(serv_ip));
printf("host %s:%d, guest %s:%d\n", serv_ip, ntohs(serv.sin_port), guest_ip, ntohs(guest.sin_port));
n = read(sockfd, buf, 100);
buf[n] = '\0';
printf("%s\n", buf);
getchar();
close(sockfd);
exit(0);
}
補充:getsockname和getpeername調度時機很重要,如果調用時機不對,則無法正確獲得地址和端口。
TCP
對于服務器來說,在bind以后就可以調用getsockname來獲取本地地址和端口,雖然這沒有什么太多的意義。getpeername只有在鏈接建立以后才調用,否則不能正確獲得對方地址和端口,所以他的參數描述字一般是鏈接描述字而非監聽套接口描述字。
對于客戶端來說,在調用socket時候內核還不會分配IP和端口,此時調用getsockname不會獲得正確的端口和地址(當然鏈接沒建立更不可能調用getpeername),當然如果調用了bind 以后可以使用getsockname。想要正確的到對方地址(一般客戶端不需要這個功能),則必須在鏈接建立以后,同樣鏈接建立以后,此時客戶端地址和端口就已經被指定,此時是調用getsockname的時機。
UDP
UDP分為鏈接和沒有鏈接2種(這個到UDP與connect可以找到相關內容)
沒有鏈接的UDP不能調用getpeername,但是可以調用getsockname,和TCP一樣,他的地址和端口不是在調用socket就指定了,而是在第一次調用sendto函數以后
已經鏈接的UDP,在調用connect以后,這2個函數都是可以用的(同樣,getpeername也沒太大意義。如果你不知道對方的地址和端口,不可能會調用connect)。
總結
以上是生活随笔為你收集整理的getsockname与getpeername的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 招行信用卡最新ATM还款方式
- 下一篇: 2020版熊猫纪念币一套多少钱?可以在这