避免端口劫持問題,可以這么做!
最近使用TCP server時(shí),發(fā)現(xiàn)如果監(jiān)控INADDR_ANY地址也就是0.0.0.0后,如果使用本機(jī)ip再去監(jiān)控同樣的端口,一樣可以監(jiān)控成功。
比如我的本機(jī)地址為10.254.1.100,我監(jiān)控0.0.0.0 1200端口 ?,再啟動(dòng)一個(gè)服務(wù)器10.254.1.100 1200端口,數(shù)據(jù)都會(huì)到10.254.1.100 1200這里去,如果關(guān)閉掉10.254.1.100 1200,則數(shù)據(jù)會(huì)到0.0.0.0 1200。這個(gè)在服務(wù)器上會(huì)導(dǎo)致很多意想不到的結(jié)果,相當(dāng)于端口被劫持了一樣,并且對(duì)調(diào)試也相當(dāng)不利。
通過設(shè)置SO_REUSEADDR可以解決這個(gè)問題。
//獨(dú)占當(dāng)前端口,防止多網(wǎng)卡情況下端口被重復(fù)使用,導(dǎo)致出現(xiàn)不可預(yù)知的情況 //不允許同一個(gè)端口在不同IP下重復(fù)監(jiān)控 char?opt?=?0; setsockopt(sockSvr,?SOL_SOCKET,?SO_REUSEADDR,?(const?char?*)&opt,?sizeof(opt)); //SO_REUSEADDR?為true?就是允許在相同的端口不同的IP地址上創(chuàng)建套接描述字。
以下是我的多網(wǎng)卡測(cè)試的例子
SOCKET?sockSvr?=?WSASocket(AF_INET,?SOCK_STREAM,?0,?0,?0,?WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET?==?sockSvr) { WSACleanup(); return?IOCP_SOCKET_ERROR; } //獨(dú)占當(dāng)前端口,防止多網(wǎng)卡情況下端口被重復(fù)使用,導(dǎo)致出現(xiàn)不可預(yù)知的情況 //不允許同一個(gè)端口在不同IP下重復(fù)監(jiān)控 char?opt?=?0; setsockopt(sockSvr,?SOL_SOCKET,?SO_REUSEADDR,?(const?char?*)&opt,?sizeof(opt)); //SO_REUSEADDR?為true?就是允許在相同的端口不同的IP地址上創(chuàng)建套接描述字。 SOCKADDR_IN?addrSvr; ZeroMemory(&addrSvr,?sizeof(SOCKADDR_IN)); addrSvr.sin_family?=?AF_INET; addrSvr.sin_port?=?htons(port); addrSvr.sin_addr.S_un.S_addr?=?htonl(INADDR_ANY); int?nRet?=?bind(sockSvr,?(SOCKADDR*)&addrSvr,?sizeof(SOCKADDR)); if(SOCKET_ERROR?==?nRet) { WSACleanup(); return?IOCP_BIND_ERROR; } nRet?=?listen(sockSvr,?MaxListen);//500:max?number?of?connect?request if(SOCKET_ERROR?==?nRet) { WSACleanup(); return?IOCP_LISTEN_ERROR; }
不管從哪個(gè)網(wǎng)卡來的連接都可以接入到本端口,這樣服務(wù)器就不用管當(dāng)前監(jiān)控的IP地址了,也不會(huì)出現(xiàn)端口劫持問題了。