找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 8811|回复: 2

关于getsockname函数的使用

[复制链接]
发表于 2012-3-9 21:33:21 | 显示全部楼层 |阅读模式
     getsockname可以获得一个与socket相关的地址。
      服务器端可以通过它得到相关客户端地址。
       而客户端也可以得到当前已连接成功的socket的ip和端口。
第二种情况在客户端不进行bind而直接连接服务器时,而且客户端需要知道当前使用哪个ip进行通信时比较有用(如多网卡的情况)。
笔者分别通过TCP和UDP协议进行测试,测试结果表明:
对于TCP连接的情况,如果不进行bind指定IP和端口,那么调用connect连接成功后,使用getsockname可以正确获得当前正在通信的socket的IP和端口地址。
而对于UDP的情况,无论是在调用sendto之后还是收到服务器返回的信息之后调用,都无法得到正确的ip地址:使用getsockname得到ip为0,端口正确。

测试用例如下:
1. TCP
  1. //client
  2. int _tmain(int argc,
  3. _TCHAR* argv[])
  4. {
  5. WSADATA wsadata;
  6. int ret = WSAStartup ( 0x0202 ,
  7. & wsadata );
  8. if ( ret != 0 || 0x0202 != wsadata.wVersion
  9. )
  10. {
  11.   cout<<"WSAStartup Error!";
  12.   return 0;
  13. }
  14. SOCKET
  15. mySock = INVALID_SOCKET;
  16. mySock = socket(AF_INET,SOCK_STREAM,0);
  17. if
  18. (mySock == INVALID_SOCKET)
  19. {
  20.   cout<<"Create Socket
  21. Error!";
  22.   return 0;
  23. }
  24. sockaddr_in
  25. addrDest;
  26. memset(&addrDest,0,sizeof(addrDest));
  27. addrDest.sin_family
  28. = AF_INET;
  29. addrDest.sin_addr.s_addr =
  30. inet_addr("10.10.44.76");
  31. addrDest.sin_port = htons(9000);
  32. ret = connect(mySock,(sockaddr*)&addrDest,sizeof(addrDest));
  33. if (ret
  34. == -1)
  35. {
  36.   cout<<GetLastError()<<endl;
  37.   return
  38. 0;
  39. }
  40. cout<<"Connect to Server Success!"<<endl;
  41. sockaddr_in addrMy;
  42. memset(&addrMy,0,sizeof(addrMy));
  43. int
  44. len = sizeof(addrMy);
  45. ret = getsockname(mySock,(sockaddr*)&addrMy,&len);
  46. if (ret !=
  47. 0)
  48. {
  49.   cout<<"Getsockname Error!"<<endl;
  50.   return
  51. 0;
  52. }
  53. cout<<"Current Socket
  54. IP:"<<inet_ntoa(addrMy.sin_addr)<<":"<<ntohs(addrMy.sin_port)<<endl;
  55. getchar();
  56. closesocket(mySock);
  57. WSACleanup();
  58. return 0;
  59. }
  60. //server
  61. int
  62. _tmain(int argc, _TCHAR* argv[])
  63. {
  64. WSADATA wsadata;
  65. int ret =
  66. WSAStartup ( 0x0202 , & wsadata );
  67. if ( ret != 0 || 0x0202 !=
  68. wsadata.wVersion )
  69. {
  70.   cout<<"WSAStartup Error!";
  71.   return
  72. 0;
  73. }
  74. SOCKET listenSock = INVALID_SOCKET;
  75. listenSock =
  76. socket(AF_INET,SOCK_STREAM,0);
  77. if (listenSock ==
  78. INVALID_SOCKET)
  79. {
  80.   cout<<"Create Socket Error!";
  81.   return
  82. 0;
  83. }
  84. sockaddr_in
  85. addrBind;
  86. memset(&addrBind,0,sizeof(addrBind));
  87. addrBind.sin_family
  88. = AF_INET;
  89. addrBind.sin_addr.s_addr = INADDR_ANY;
  90. addrBind.sin_port =
  91. htons(9000);
  92. ret = bind(listenSock,(sockaddr*)&addrBind,sizeof(addrBind));
  93. if
  94. (ret == SOCKET_ERROR)
  95. {
  96.   cout<<"Bind
  97. Error"<<endl;
  98.   return 0;
  99. }
  100. ret =
  101. listen(listenSock,5);
  102. if (ret != 0)
  103. {
  104.   cout<<"Listen
  105. Error"<<endl;
  106.   return 0;
  107. }
  108. SOCKET
  109. conSock;
  110. sockaddr_in addrCon;
  111. int len = sizeof(addrCon);
  112. while
  113. (true)
  114. {
  115.   conSock =
  116. accept(listenSock,(sockaddr*)&addrCon,&len);
  117.   if (conSock ==
  118. INVALID_SOCKET)
  119.   {
  120.    cout<<"Accept
  121. Error"<<endl;
  122.    return
  123. 0;
  124.   }
  125.   cout<<inet_ntoa(addrCon.sin_addr)<<" Connect to
  126. Server!"<<endl;
  127.   
  128. }
  129. closesocket(conSock);
  130. closesocket(listenSock);
  131. WSACleanup();
  132. return 0;
  133. }
复制代码

2. UDP
  1. //client
  2. int
  3. _tmain(int argc, _TCHAR* argv[])
  4. {
  5. WSADATA wsadata;
  6. int ret =
  7. WSAStartup ( 0x0202 , & wsadata );
  8. if ( ret != 0 || 0x0202 !=
  9. wsadata.wVersion )
  10. {
  11.   cout<<"WSAStartup Error!";
  12.   return
  13. 0;
  14. }
  15. SOCKET mySock = INVALID_SOCKET;
  16. mySock =
  17. socket(AF_INET,SOCK_DGRAM,0);
  18. if (mySock ==
  19. INVALID_SOCKET)
  20. {
  21.   cout<<"Create Socket Error!";
  22.   return
  23. 0;
  24. }
  25. sockaddr_in
  26. addrDest;
  27. memset(&addrDest,0,sizeof(addrDest));
  28. addrDest.sin_family
  29. = AF_INET;
  30. addrDest.sin_addr.s_addr =
  31. inet_addr("10.10.44.76");
  32. addrDest.sin_port = htons(9000);
  33. //set non-blocking
  34. int nMode = 1;
  35. ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
  36. char
  37. sendchar[20];
  38. strcpy_s(sendchar,"login");
  39. sendto(mySock,sendchar,strlen(sendchar)+1,0,(sockaddr*)&addrDest,sizeof(sockaddr));
  40. //get send socket ip
  41. sockaddr_in
  42. addrMy;
  43. memset(&addrMy,0,sizeof(addrMy));
  44. int leng =
  45. sizeof(addrMy);
  46. ret =
  47. getsockname(mySock,(sockaddr*)&addrMy,&leng);
  48. if (ret !=
  49. 0)
  50. {
  51.   cout<<"Getsockname Error!"<<endl;
  52.   return
  53. 0;
  54. }
  55. cout<<"Current Socket
  56. IP:"<<inet_ntoa(addrMy.sin_addr)<<":"<<ntohs(addrMy.sin_port)<<endl;
  57. char recvchar[20];
  58. sockaddr_in
  59. addrRev;
  60. memset(&addrRev,0,sizeof(addrRev));
  61. memset(recvchar,0,20);
  62. int
  63. len = sizeof(sockaddr);
  64. while (true)
  65. {
  66.   if
  67. (recvfrom(mySock,recvchar,20,0,(sockaddr*)&addrRev,&len) ==
  68. SOCKET_ERROR)
  69.   {
  70.    if (GetLastError() == WSAEWOULDBLOCK ||
  71. GetLastError() ==
  72. 10054)
  73.    {
  74.     continue;
  75.    }
  76.    else
  77.    {
  78.     cout<<"Receive
  79. Error!"<<GetLastError()<<endl;
  80.     return
  81. 0;
  82.    }
  83.   }
  84.   cout<<"login
  85. success!"<<endl;
  86.   //get send socket ip
  87.   sockaddr_in
  88. addrMy;
  89.   memset(&addrMy,0,sizeof(addrMy));
  90.   int leng =
  91. sizeof(addrMy);
  92.   ret =
  93. getsockname(mySock,(sockaddr*)&addrMy,&leng);
  94.   if (ret !=
  95. 0)
  96.   {
  97.    cout<<"Getsockname Error!"<<endl;
  98.    return
  99. 0;
  100.   }
  101.   cout<<"Current Socket
  102. IP:"<<inet_ntoa(addrMy.sin_addr)<<":"<<ntohs(addrMy.sin_port)<<endl;
  103. }
  104. return 0;
  105. }
  106. //server
  107. int _tmain(int argc, _TCHAR*
  108. argv[])
  109. {
  110. WSADATA wsadata;
  111. int ret = WSAStartup ( 0x0202 , &
  112. wsadata );
  113. if ( ret != 0 || 0x0202 != wsadata.wVersion
  114. )
  115. {
  116.   cout<<"WSAStartup Error!";
  117.   return 0;
  118. }
  119. SOCKET
  120. mySock = INVALID_SOCKET;
  121. mySock = socket(AF_INET,SOCK_DGRAM,0);
  122. if
  123. (mySock == INVALID_SOCKET)
  124. {
  125.   cout<<"Create Socket
  126. Error!";
  127.   return 0;
  128. }
  129. sockaddr_in
  130. addrBind;
  131. memset(&addrBind,0,sizeof(addrBind));
  132. addrBind.sin_family
  133. = AF_INET;
  134. addrBind.sin_addr.s_addr = INADDR_ANY;
  135. addrBind.sin_port =
  136. htons(9000);
  137. ret =
  138. bind(mySock,(sockaddr*)&addrBind,sizeof(addrBind));
  139. if (ret ==
  140. SOCKET_ERROR)
  141. {
  142.   cout<<"Bind Error"<<endl;
  143.   return
  144. 0;
  145. }
  146. //set non-blocking
  147. int nMode = 1;
  148. ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
  149. char recvchar[20];
  150. sockaddr_in
  151. addrRev;
  152. memset(&addrRev,0,sizeof(addrRev));
  153. memset(recvchar,0,20);
  154. int
  155. len = sizeof(sockaddr);
  156. while (true)
  157. {
  158.   if
  159. (recvfrom(mySock,recvchar,20,0,(sockaddr*)&addrRev,&len) ==
  160. SOCKET_ERROR)
  161.   {
  162.    if (GetLastError() == WSAEWOULDBLOCK ||
  163. GetLastError() ==
  164. 10054)
  165.    {
  166.     continue;
  167.    }
  168.    else
  169.    {
  170.     cout<<"Receive
  171. Error!"<<GetLastError()<<endl;
  172.     return
  173. 0;
  174.    }
  175.   }
  176.   cout<<recvchar<<" from
  177. "<<inet_ntoa(addrRev.sin_addr)<<":"<<ntohs(addrRev.sin_port)<<endl;
  178.   sendto(mySock,recvchar,strlen(recvchar)+1,0,(sockaddr*)&addrRev,sizeof(sockaddr));
  179. }
  180. return 0;
  181. }
复制代码



 楼主| 发表于 2012-10-19 10:13:03 | 显示全部楼层
刷新,冲掉垃圾广告标题。
发表于 2013-9-26 17:25:55 | 显示全部楼层
广告真是个头疼的问题
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 10:47 , Processed in 0.022324 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表