getpeername函数与getsockname函数的介绍
getpeername函數用于獲取與某個套接字關聯的外地協議地址
getsockname函數用于獲取與某個套接字關聯的本地協議地址
?
函數定義如下:
#include<sys/socket.h>int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen); 調用成功,則返回0,如果調用出錯,則返回-1?
getpeername只有在連接建立以后才調用,否則不能正確獲得對方地址和端口,所以它的參數描述字一般是已連接描述字而非監聽套接口描述字。
? ? 沒有連接的UDP不能調用getpeername,但是可以調用getsockname和TCP一樣,它的地址和端口不是在調用socket就指定了,而是在第一次調用sendto函數以后。
? ? 已經連接的UDP,在調用connect以后,這2個函數(getsockname,getpeername)都是可以用的。但是這時意義不大,因為已經連接(connect)的UDP已經知道對方的地址。
需要這兩個函數的理由如下:
-
在一個沒有調用bind的TCP客戶上,connect成功返回后,getsockname用于返回由內核賦予該連接的本地IP地址和本地端口號。
-
在以端口號為0調用bind(告知內核去選擇本地臨時端口號)后,getsockname用于返回由內核賦予的本地端口號。
-
在一個以通配IP地址調用bind的TCP服務器上,與某個客戶的連接一旦建立(accept成功返回),getsockname就可以用于返回由內核賦予該連接的本地IP地址。在這樣的調用中,套接字描述符參數必須是已連接套接字的描述符,而不是監聽套接字的描述符。
-
當一個服務器的是由調用過accept的某個進程通過調用exec執行程序時,它能夠獲取客戶身份的唯一途徑便是調用getpeername。
?
手冊中介紹
GETPEERNAME(2) Linux Programmer's Manual GETPEERNAME(2)NAMEgetpeername - get name of connected peer socketSYNOPSIS#include <sys/socket.h>int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);DESCRIPTIONgetpeername() returns the address of the peer connected to the socket sockfd, in the buffer pointed to by addr. The addrlen argument should be initialized to indicate theamount of space pointed to by addr. On return it contains the actual size of the name returned (in bytes). The name is truncated if the buffer provided is too small.The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.RETURN VALUEOn success, zero is returned. On error, -1 is returned, and errno is set appropriately.ERRORSEBADF The argument sockfd is not a valid descriptor.EFAULT The addr argument points to memory not in a valid part of the process address space.EINVAL addrlen is invalid (e.g., is negative).ENOBUFSInsufficient resources were available in the system to perform the operation.ENOTCONNThe socket is not connected.ENOTSOCKThe file descriptor sockfd does not refer to a socket.CONFORMING TOPOSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (getpeername() first appeared in 4.2BSD).NOTESThe third argument of getpeername() is in reality an int * (and this is what 4.x BSD and libc4 and libc5 have). Some POSIX confusion resulted in the present socklen_t, alsoused by glibc. See also accept(2).For stream sockets, once a connect(2) has been performed, either socket can call getpeername() to obtain the address of the peer socket. On the other hand, datagram socketsare connectionless. Calling connect(2) on a datagram socket merely sets the peer address for outgoing datagrams sent with write(2) or recv(2). The caller of connect(2) canuse getpeername() to obtain the peer address that it earlier set for the socket. However, the peer socket is unaware of this information, and calling getpeername() on thepeer socket will return no useful information (unless a connect(2) call was also executed on the peer). Note also that the receiver of a datagram can obtain the address ofthe sender when using recvfrom(2).SEE ALSOaccept(2), bind(2), getsockname(2), ip(7), socket(7), unix(7)COLOPHONThis page is part of release 4.04 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest version of this page, can befound at http://www.kernel.org/doc/man-pages/.Linux 2015-12-28 GETPEERNAME(2) GETSOCKNAME(2) Linux Programmer's Manual GETSOCKNAME(2)NAMEgetsockname - get socket nameSYNOPSIS#include <sys/socket.h>int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);DESCRIPTIONgetsockname() returns the current address to which the socket sockfd is bound, in the buffer pointed to by addr. The addrlen argument should be initialized to indicate theamount of space (in bytes) pointed to by addr. On return it contains the actual size of the socket address.The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.RETURN VALUEOn success, zero is returned. On error, -1 is returned, and errno is set appropriately.ERRORSEBADF The argument sockfd is not a valid descriptor.EFAULT The addr argument points to memory not in a valid part of the process address space.EINVAL addrlen is invalid (e.g., is negative).ENOBUFSInsufficient resources were available in the system to perform the operation.ENOTSOCKThe file descriptor sockfd does not refer to a socket.CONFORMING TOPOSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (getsockname() first appeared in 4.2BSD).NOTESThe third argument of getsockname() is in reality an int * (and this is what 4.x BSD and libc4 and libc5 have). Some POSIX confusion resulted in the present socklen_t, alsoused by glibc. See also accept(2).SEE ALSObind(2), socket(2), getifaddrs(3), ip(7), socket(7), unix(7)COLOPHONThis page is part of release 4.04 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest version of this page, can befound at http://www.kernel.org/doc/man-pages/.Linux 2015-12-28 GETSOCKNAME(2)我們可以通過套接字描述符來獲取自己的IP地址和連接對端的IP地址
服務器代碼:
/*服務器端*/ #define MAXLINE 4096 #define PORT 6563 #define LISTENQ 1024 #include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> #include<string.h> #include<arpa/inet.h>int main() {int listenfd, connfd;struct sockaddr_in servaddr;//服務器綁定的地址struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分別表示監聽的地址,連接的本地地址,連接的對端地址int listendAddrLen, connectedAddrLen, peerLen;char ipAddr[INET_ADDRSTRLEN];//保存點分十進制的地址listenfd = socket(AF_INET, SOCK_STREAM, 0);memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(PORT);bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));//服務器端綁定地址listen(listenfd, LISTENQ);listendAddrLen = sizeof(listendAddr);getsockname(listenfd, (struct sockaddr *)&listendAddr, &listendAddrLen);//獲取監聽的地址和端口printf("listen address = %s:%d\n", inet_ntoa(listendAddr.sin_addr), ntohs(listendAddr.sin_port));while(1) {connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);connectedAddrLen = sizeof(connectedAddr);getsockname(connfd, (struct sockaddr *)&connectedAddr, &connectedAddrLen);//獲取connfd表示的連接上的本地地址printf("connected server address = %s:%d\n", inet_ntoa(connectedAddr.sin_addr), ntohs(connectedAddr.sin_port));getpeername(connfd, (struct sockaddr *)&peerAddr, &peerLen); //獲取connfd表示的連接上的對端地址printf("connected peer address = %s:%d\n", inet_ntop(AF_INET, &peerAddr.sin_addr, ipAddr, sizeof(ipAddr)), ntohs(peerAddr.sin_port));}return 0; }客戶端代碼:
/*客戶端*/ #define PORT 6563 #include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> #include<string.h> #include<arpa/inet.h>int main(int argc, char **argv) {struct sockaddr_in servaddr;//服務器端地址struct sockaddr_in clientAddr;//客戶端地址int sockfd; int clientAddrLen = sizeof(clientAddr);char ipAddress[INET_ADDRSTRLEN];//保存點分十進制的ip地址if(argc < 2) {printf("parameter error");}sockfd = socket(AF_INET, SOCK_STREAM, 0);memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT); if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {printf("server address error\n");//地址參數不合法}connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//向服務器端發起連接請求getsockname(sockfd, (struct sockaddr*)&clientAddr, &clientAddrLen);//獲取sockfd表示的連接上的本地地址printf("client:client ddress = %s:%d\n", inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress)), ntohs(clientAddr.sin_port));return 0; }?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的getpeername函数与getsockname函数的介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 作者:褚金翔(1979-),男,中国农业
- 下一篇: socket中使用多线程创建并发服务器