转自出处
getsockname可以获得一个与socket相关的地址。
服务器端可以通过它得到相关客户端地址。
而客户端也可以得到当前已连接成功的socket的ip和端口。
第二种情况在客户端不进行bind而直接连接服务器时,而且客户端需要知道当前使用哪个ip进行通信时比较有用(如多网卡的情况)。
笔者分别通过TCP和UDP协议进行测试,测试结果表明:
对于TCP连接的情况,如果不进行bind指定IP和端口,那么调用connect连接成功后,使用getsockname可以正确获得当前正在通信的socket的IP和端口地址。
而对于UDP的情况,无论是在调用sendto之后还是收到服务器返回的信息之后调用,都无法得到正确的ip地址:使用getsockname得到ip为0,端口正确。
测试用例如下:
1. TCP
//client
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsadata;
int ret = WSAStartup ( 0x0202 , & wsadata );
if ( ret != 0 || 0x0202 != wsadata.wVersion )
{
cout<<"WSAStartup Error!";
return 0;
}
SOCKET mySock = INVALID_SOCKET;
mySock = socket(AF_INET,SOCK_STREAM,0);
if (mySock == INVALID_SOCKET)
{
cout<<"Create Socket Error!";
return 0;
}
sockaddr_in addrDest;
memset(&addrDest,0,sizeof(addrDest));
addrDest.sin_family = AF_INET;
addrDest.sin_addr.s_addr = inet_addr("10.10.44.76");
addrDest.sin_port = htons(9000);
ret = connect(mySock,(sockaddr*)&addrDest,sizeof(addrDest)); ret = getsockname(mySock,(sockaddr*)&addrMy,&len); cout<<"Current Socket IP:"< getchar(); closesocket(mySock); return 0; sockaddr_in addrBind; ret = bind(listenSock,(sockaddr*)&addrBind,sizeof(addrBind)); closesocket(conSock); WSACleanup(); return 0; sockaddr_in addrDest; char sendchar[20]; sendto(mySock,sendchar,strlen(sendchar)+1,0,(sockaddr*)&addrDest,sizeof(sockaddr)); //get send socket ip ret = getsockname(mySock,(sockaddr*)&addrMy,&leng); cout<<"Current Socket IP:"< char recvchar[20]; cout<<"login success!"< //get send socket ip ret = getsockname(mySock,(sockaddr*)&addrMy,&leng); cout<<"Current Socket IP:"< return 0; sockaddr_in addrBind; ret = bind(mySock,(sockaddr*)&addrBind,sizeof(addrBind)); //set non-blocking char recvchar[20]; sendto(mySock,recvchar,strlen(recvchar)+1,0,(sockaddr*)&addrRev,sizeof(sockaddr)); return 0;
if (ret == -1)
{
cout<
}
cout<<"Connect to Server Success!"<
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int len = sizeof(addrMy);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
WSACleanup();
}
//server
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsadata;
int ret = WSAStartup ( 0x0202 , & wsadata );
if ( ret != 0 || 0x0202 != wsadata.wVersion )
{
cout<<"WSAStartup Error!";
return 0;
}
SOCKET listenSock = INVALID_SOCKET;
listenSock = socket(AF_INET,SOCK_STREAM,0);
if (listenSock == INVALID_SOCKET)
{
cout<<"Create Socket Error!";
return 0;
}
memset(&addrBind,0,sizeof(addrBind));
addrBind.sin_family = AF_INET;
addrBind.sin_addr.s_addr = INADDR_ANY;
addrBind.sin_port = htons(9000);
if (ret == SOCKET_ERROR)
{
cout<<"Bind Error"<
}
ret = listen(listenSock,5);
if (ret != 0)
{
cout<<"Listen Error"<
}
SOCKET conSock;
sockaddr_in addrCon;
int len = sizeof(addrCon);
while (true)
{
conSock = accept(listenSock,(sockaddr*)&addrCon,&len);
if (conSock == INVALID_SOCKET)
{
cout<<"Accept Error"<
}
cout<
}
closesocket(listenSock);
}
2. UDP
//client
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsadata;
int ret = WSAStartup ( 0x0202 , & wsadata );
if ( ret != 0 || 0x0202 != wsadata.wVersion )
{
cout<<"WSAStartup Error!";
return 0;
}
SOCKET mySock = INVALID_SOCKET;
mySock = socket(AF_INET,SOCK_DGRAM,0);
if (mySock == INVALID_SOCKET)
{
cout<<"Create Socket Error!";
return 0;
}
memset(&addrDest,0,sizeof(addrDest));
addrDest.sin_family = AF_INET;
addrDest.sin_addr.s_addr = inet_addr("10.10.44.76");
addrDest.sin_port = htons(9000);
//set non-blocking
int nMode = 1;
ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
strcpy_s(sendchar,"login");
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int leng = sizeof(addrMy);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
sockaddr_in addrRev;
memset(&addrRev,0,sizeof(addrRev));
memset(recvchar,0,20);
int len = sizeof(sockaddr);
while (true)
{
if (recvfrom(mySock,recvchar,20,0,(sockaddr*)&addrRev,&len) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK || GetLastError() == 10054)
{
continue;
}
else
{
cout<<"Receive Error!"<
}
}
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int leng = sizeof(addrMy);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
}
//server
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsadata;
int ret = WSAStartup ( 0x0202 , & wsadata );
if ( ret != 0 || 0x0202 != wsadata.wVersion )
{
cout<<"WSAStartup Error!";
return 0;
}
SOCKET mySock = INVALID_SOCKET;
mySock = socket(AF_INET,SOCK_DGRAM,0);
if (mySock == INVALID_SOCKET)
{
cout<<"Create Socket Error!";
return 0;
}
memset(&addrBind,0,sizeof(addrBind));
addrBind.sin_family = AF_INET;
addrBind.sin_addr.s_addr = INADDR_ANY;
addrBind.sin_port = htons(9000);
if (ret == SOCKET_ERROR)
{
cout<<"Bind Error"<
}
int nMode = 1;
ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
sockaddr_in addrRev;
memset(&addrRev,0,sizeof(addrRev));
memset(recvchar,0,20);
int len = sizeof(sockaddr);
while (true)
{
if (recvfrom(mySock,recvchar,20,0,(sockaddr*)&addrRev,&len) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK || GetLastError() == 10054)
{
continue;
}
else
{
cout<<"Receive Error!"<
}
}
cout<
}
}