getsockname奇怪问题?

本文探讨了一个关于getsockname函数使用的奇怪现象:当该函数置于if条件语句中时无法正常工作并返回空值,而在外部调用时则能正确返回本地套接字地址信息。文章通过具体代码示例展示了这一问题。

2009-07-0423:23:09


extern int errno;
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <strings.h>
#define SA struct sockaddr
#define MAXLINE 4096
int main(int argc,char **argv)
{
    int n,sockfd;
    socklen_t sslen;
    char recvline[MAXLINE];
    struct sockaddr_in servsock,ss;
    if( argc != 2)
 printf("paramer is error");
    if( (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
 printf("socket error:%s/n",strerror(errno));
    bzero(&servsock,sizeof(servsock));
    servsock.sin_port = htons(50000);
    servsock.sin_family = AF_INET;

    if( (inet_pton(AF_INET,argv[1],&servsock.sin_addr.s_addr) <= 0))
 printf("inet_pton error:%s/n",strerror(errno));
/*    bzero(&ss,sizeof(ss));
    ss.sin_port = htons(30000);
    ss.sin_family = AF_INET;
    ss.sin_addr.s_addr = htonl(INADDR_ANY);*/
    sslen = sizeof(struct sockaddr_in);
    //inet_pton(AF_INET,"192.168.1.20",&ss.sin_addr.s_addr);
    //bind(sockfd,(SA *)&ss,sslen);
    if( connect(sockfd,(SA *)&servsock,sizeof(servsock)) < 0)
 printf("connect error:%s/n",strerror(errno));
if( getsockname(sockfd, (SA *)&ss,&sslen) < 0)
 printf("getsockname error:%s/n",strerror(errno));
    else
 printf("Bind IP = [%s]/tport = [%s]/n",
  inet_ntop(AF_INET,&ss.sin_addr.s_addr,recvline,MAXLINE),
  ntohs(ss.sin_port));
 /*   printf("%s/n",recvline);
getsockname(sockfd, (SA *)&ss,&sslen);
    printf("sslen=%d/t[%s]/t[%d]/n",sslen,inet_ntop(AF_INET,&ss.sin_addr.s_addr,recvline,sizeof(recvline)), ntohs(ss.sin_port));*/
    bzero(recvline,sizeof(recvline));
    while( (n = read(sockfd,recvline,MAXLINE)) > 0)
    {
 recvline[n] = 0;
 if( fputs(recvline,stdout) == EOF)
     printf("fputs error/n");
    }
    if(n < 0)
 printf("read error/n");
    exit(0);
}

 

很奇怪的问题不知道为什么getsockname放到if里就不能显示输出为空

而放在外面就好用

现在注释的那段程序。

0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getaddrinfo 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 timegm 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 difftime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getnameinfo 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 nanosleep 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strncat 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 unlink 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strcspn 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shm_open 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fgets 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ftruncate 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sendto 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __libc_start_main 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_mutex_lock 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sigfillset 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 epoll_ctl 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 clock_gettime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 localtime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 time 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 recvfrom 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fileno 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 readdir 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 rename 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strtod 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 atoi 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 inet_aton 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 qsort 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.33 fstat 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 readlink 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getpid 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 socket 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pselect 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 snprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strcat 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strncasecmp 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 putchar 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fseeko 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_exit 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sigaction 0000000000000000 DO *UND* 0000000000000000 GLIBC_2.17 __stack_chk_guard 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 memcpy 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 htons 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __ctype_b_loc 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fread 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 gethostbyname 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strncpy 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 exit 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 cos 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 munmap 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ftello 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strftime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strrchr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 localtime_r 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mktime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 select 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 tcdrain 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __cxa_atexit 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sync 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sleep 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shutdown 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 gmtime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strstr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shmat 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 _exit 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ntohs 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pclose 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getsockopt 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mmap 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 secure_getenv 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fputc 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 clock 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 closedir 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __isoc99_sscanf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strncmp 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mq_open 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 inet_pton 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 abort 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_join 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __isoc99_fscanf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strspn 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __sigsetjmp 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 usleep 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ferror 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fgetc 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 uname 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fflush 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_setname_np 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_mutex_destroy 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 remove 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __assert_fail 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.25 getrandom 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __errno_location 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 freeaddrinfo 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 recv 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 read 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mprotect 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sigprocmask 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 perror 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 signal 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strtoll 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mlock 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 syscall 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 siglongjmp 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shmdt 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fopen 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mq_send 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 tolower 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 listen 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __stack_chk_fail 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 inet_ntop 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 write 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mq_close 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 socketpair 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 vprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 rand 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 cfgetospeed 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __getauxval 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 poll 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 gai_strerror 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 feof 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 memcmp 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fseek 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_cancel 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mq_unlink 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 send 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 cfsetispeed 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 bind 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_mutex_init 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fclose 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ioctl 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strtoul 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 setvbuf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getpeername 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_create 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_mutex_unlock 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 epoll_create1 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strtol 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sqrt 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 tcgetattr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sin 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 opendir 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strdup 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 calloc 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getenv 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 vsnprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 popen 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 setsockopt 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mq_receive 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 gettimeofday 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strchr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 mkdir 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __xpg_strerror_r 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getauxval 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 memchr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sysconf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 accept 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shmget 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 cfsetospeed 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 reboot 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 atan2 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 puts 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 tcsetattr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 epoll_wait 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sched_yield 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strerror 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_testcancel 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fwrite 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 madvise 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 inet_addr 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 sigdelset 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fputs 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 printf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strcpy 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 freopen 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 memmove 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 close 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 vfprintf 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 connect 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.33 stat 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 __ctype_tolower_loc 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 strlen 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fopen64 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 ftell 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 fcntl 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 utime 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 pthread_self 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 shm_unlink 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 srand 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 open 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 getsockname 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 memset 00000000007b2560 g DO .bss 0000000000000008 GLIBC_2.17 stdout 0000000000403c60 DF *UND* 0000000000000000 GLIBC_2.17 realloc 0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.25 getentropy 00000000007b2568 g DO .bss 0000000000000008 GLIBC_2.17 stderr 00000000007b2570 g DO .bss 0000000000000008 GLIBC_2.17 stdin 0000000000404130 DF *UND* 0000000000000000 GLIBC_2.17 malloc 00000000004043b0 DF *UND* 0000000000000000 GLIBC_2.17 free 0000000000404220 DF *UND* 0000000000000000 GLIBC_2.17 strcmp 0000000000404520 DF *UND* 0000000000000000 GLIBC_2.17 strcasecmp
11-21
<think> 我们正在讨论网络编程中的getsockname函数。该函数用于获取一个套接字的本地协议地址(对于IPv4是IP地址和端口号)。 函数原型如下: #include <sys/socket.h> int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 参数说明: - sockfd: 套接字描述符 - addr: 指向存放返回地址的结构体指针(例如struct sockaddr_in) - addrlen: 指向一个socklen_t的指针,在调用时初始化为addr指向的存储区的长度,函数返回时该值会被设置为实际地址的长度。 返回值: - 成功返回0,失败返回-1并设置errno。 典型使用场景: - 当调用bind时端口号为0(由内核选择临时端口)时,可以通过getsockname获取内核分配的端口号。 - 当进程在调用accept之后,可以通过getsockname获取连接中本地的套接字地址。 - 在未绑定地址的套接字上,可以获取系统分配的地址(通常为0.0.0.0)和端口号。 注意:getsockname只能用于已连接的套接字(如TCP)或已绑定的套接字(UDP)。对于未绑定的套接字,其行为是未定义的(可能返回0.0.0.0和0端口)。 下面是一个示例程序,展示如何使用getsockname获取本地地址和端口。 </think>### `getsockname` 函数详解 `getsockname()` 是 Unix/Linux 网络编程中的核心函数,用于获取与套接字关联的本地协议地址(IP地址和端口号)。以下是详细解析: #### 函数原型 ```c #include <sys/socket.h> int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` #### 参数说明 | 参数 | 类型 | 描述 | |------|------|------| | `sockfd` | `int` | 套接字文件描述符 | | `addr` | `struct sockaddr*` | 指向存储地址信息的缓冲区 | | `addrlen` | `socklen_t*` | 输入时为缓冲区大小,输出时为实际地址长度 | #### 返回值 - 成功:返回 `0` - 失败:返回 `-1` 并设置 `errno` --- ### 核心功能与应用场景 1. **获取绑定地址** - 当使用 `bind()` 绑定到 `INADDR_ANY` (0.0.0.0) 时 - 当端口号指定为 `0`(由内核分配随机端口)时 2. **获取连接信息** - 获取已连接套接字的本地端点地址 - 确定 UDP 套接字的实际绑定地址 3. **诊断工具** - 调试网络程序时验证绑定地址 - 在多宿主主机上确定使用的网络接口 --- ### 使用示例代码 ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 绑定到任意地址和随机端口 struct sockaddr_in serv_addr = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, // 任意本地接口 .sin_port = 0 // 由内核分配端口 }; if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { perror("bind failed"); close(sockfd); exit(EXIT_FAILURE); } // 获取实际绑定地址 struct sockaddr_in actual_addr; socklen_t addr_len = sizeof(actual_addr); if (getsockname(sockfd, (struct sockaddr*)&actual_addr, &addr_len) < 0) { perror("getsockname failed"); close(sockfd); exit(EXIT_FAILURE); } // 转换并打印结果 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &actual_addr.sin_addr, ip_str, sizeof(ip_str)); printf("Bound to: %s:%d\n", ip_str, ntohs(actual_addr.sin_port)); close(sockfd); return 0; } ``` #### 代码解析: 1. **套接字创建**:创建 TCP 流套接字 2. **特殊绑定**: - `INADDR_ANY`:绑定到所有可用网络接口 - 端口 `0`:由内核自动分配可用端口 3. **地址获取**: - 调用 `getsockname()` 获取实际绑定地址 - `addr_len` 作为输入输出参数 4. **地址转换**: - `inet_ntop()`:将二进制 IP 转为可读字符串 - `ntohs()`:网络字节序转主机字节序(端口号) --- ### 典型输出示例 ``` Bound to: 0.0.0.0:34652 // 绑定到所有接口,随机端口 Bound to: 192.168.1.100:80 // 绑定到特定接口 ``` --- ### 注意事项 1. **地址族兼容性** ```c // 支持 IPv4 和 IPv6 struct sockaddr_storage addr; socklen_t len = sizeof(addr); getsockname(sockfd, (struct sockaddr*)&addr, &len); if (addr.ss_family == AF_INET) { // IPv4 处理 } else if (addr.ss_family == AF_INET6) { // IPv6 处理 } ``` 2. **错误处理** - `EBADF`:无效文件描述符 - `ENOTSOCK`:描述符不是套接字 - `ENOBUFS`:系统资源不足 - `EFAULT`:addr 指向无效内存 3. **相关函数对比** | 函数 | 描述 | 区别 | |------|------|------| | `getsockname()` | 获取本地地址 | 用于连接的发起方 | | `getpeername()` | 获取对端地址 | 用于连接的接收方 | | `bind()` | 设置本地地址 | 需在连接前调用 | --- ### 实际应用场景 1. **FTP 服务器** ```c // 获取数据通道的实际端口 getsockname(data_sock, &addr, &len); send_control_msg("227 Entering Passive Mode (%s,%d,%d)", ip, port>>8, port&0xFF); ``` 2. **端口转发工具** ```c // 确定监听的随机端口 getsockname(listen_sock, &addr, &len); printf("Listening on port %d\n", ntohs(addr.sin_port)); ``` 3. **多宿主主机服务** ```c // 确定客户端使用的接口 getsockname(conn_sock, &addr, &len); if (inet_addr("192.168.1.0") == (addr.sin_addr.s_addr & 0xFFFFFF00)) { // 内部网络处理逻辑 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值