转自出处
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));
if (ret == -1)
{
cout<
}
cout<<"Connect to Server Success!"<
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int len = sizeof(addrMy);
ret = getsockname(mySock,(sockaddr*)&addrMy,&len);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
cout<<"Current Socket IP:"<
closesocket(mySock);
WSACleanup();
return 0;
}
//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;
}
sockaddr_in addrBind;
memset(&addrBind,0,sizeof(addrBind));
addrBind.sin_family = AF_INET;
addrBind.sin_addr.s_addr = INADDR_ANY;
addrBind.sin_port = htons(9000);
ret = bind(listenSock,(sockaddr*)&addrBind,sizeof(addrBind));
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(conSock);
closesocket(listenSock);
WSACleanup();
return 0;
}
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;
}
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);
//set non-blocking
int nMode = 1;
ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
char sendchar[20];
strcpy_s(sendchar,"login");
sendto(mySock,sendchar,strlen(sendchar)+1,0,(sockaddr*)&addrDest,sizeof(sockaddr));
//get send socket ip
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int leng = sizeof(addrMy);
ret = getsockname(mySock,(sockaddr*)&addrMy,&leng);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
cout<<"Current Socket IP:"<
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<<"login success!"<
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int leng = sizeof(addrMy);
ret = getsockname(mySock,(sockaddr*)&addrMy,&leng);
if (ret != 0)
{
cout<<"Getsockname Error!"<
}
cout<<"Current Socket IP:"<
return 0;
}
//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;
}
sockaddr_in addrBind;
memset(&addrBind,0,sizeof(addrBind));
addrBind.sin_family = AF_INET;
addrBind.sin_addr.s_addr = INADDR_ANY;
addrBind.sin_port = htons(9000);
ret = bind(mySock,(sockaddr*)&addrBind,sizeof(addrBind));
if (ret == SOCKET_ERROR)
{
cout<<"Bind Error"<
}
//set non-blocking
int nMode = 1;
ioctlsocket(mySock,FIONBIO,(u_long FAR*) &nMode);
char recvchar[20];
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<
}
【Linux|关于getsockname函数的使用】return 0;
}
推荐阅读
- Linux|109 个实用 shell 脚本
- linux笔记|linux 常用命令汇总(面向面试)
- Application|linux应用编程笔记(5)系统调用文件编程方法实现文件复制
- Linux|Linux--网络基础
- linux|apt update和apt upgrade命令 - 有什么区别()
- linux|2022年云原生趋势
- Go|Docker后端部署详解(Go+Nginx)
- 开源生态|GPL、MIT、Apache...开发者如何选择开源协议(一文讲清根本区别)