getpeername函数与getsockname函数的介绍
getpeername函數(shù)用于獲取與某個套接字關(guān)聯(lián)的外地協(xié)議地址
getsockname函數(shù)用于獲取與某個套接字關(guān)聯(lián)的本地協(xié)議地址
?
函數(shù)定義如下:
#include<sys/socket.h>int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen); 調(diào)用成功,則返回0,如果調(diào)用出錯,則返回-1?
getpeername只有在連接建立以后才調(diào)用,否則不能正確獲得對方地址和端口,所以它的參數(shù)描述字一般是已連接描述字而非監(jiān)聽套接口描述字。
? ? 沒有連接的UDP不能調(diào)用getpeername,但是可以調(diào)用getsockname和TCP一樣,它的地址和端口不是在調(diào)用socket就指定了,而是在第一次調(diào)用sendto函數(shù)以后。
? ? 已經(jīng)連接的UDP,在調(diào)用connect以后,這2個函數(shù)(getsockname,getpeername)都是可以用的。但是這時意義不大,因為已經(jīng)連接(connect)的UDP已經(jīng)知道對方的地址。
需要這兩個函數(shù)的理由如下:
-
在一個沒有調(diào)用bind的TCP客戶上,connect成功返回后,getsockname用于返回由內(nèi)核賦予該連接的本地IP地址和本地端口號。
-
在以端口號為0調(diào)用bind(告知內(nèi)核去選擇本地臨時端口號)后,getsockname用于返回由內(nèi)核賦予的本地端口號。
-
在一個以通配IP地址調(diào)用bind的TCP服務(wù)器上,與某個客戶的連接一旦建立(accept成功返回),getsockname就可以用于返回由內(nèi)核賦予該連接的本地IP地址。在這樣的調(diào)用中,套接字描述符參數(shù)必須是已連接套接字的描述符,而不是監(jiān)聽套接字的描述符。
-
當(dāng)一個服務(wù)器的是由調(diào)用過accept的某個進程通過調(diào)用exec執(zhí)行程序時,它能夠獲取客戶身份的唯一途徑便是調(diào)用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地址
服務(wù)器代碼:
/*服務(wù)器端*/ #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;//服務(wù)器綁定的地址struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分別表示監(jiān)聽的地址,連接的本地地址,連接的對端地址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));//服務(wù)器端綁定地址listen(listenfd, LISTENQ);listendAddrLen = sizeof(listendAddr);getsockname(listenfd, (struct sockaddr *)&listendAddr, &listendAddrLen);//獲取監(jiān)聽的地址和端口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;//服務(wù)器端地址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");//地址參數(shù)不合法}connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//向服務(wù)器端發(fā)起連接請求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; }?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的getpeername函数与getsockname函数的介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 作者:褚金翔(1979-),男,中国农业
- 下一篇: socket中使用多线程创建并发服务器