socket通过多网卡收发数据
1.?? 通過bind機制,?? socket必須要調用bind才能發送tcp包。 bind調用時需要一個ip地址。一般一臺機器的多網口都要配置不同的ip地址(路由器除外,路由器是一個網橋設備,只是負責轉發包,所以其它的端口一般沒有ip地址)。
2.?? 通過ioctl來設置打開的socket.???? (ioctl (fd, SIOCGIFINDEX, &ifr)==0;
?
TCP編程時不管是客戶端還是服務器端,都要調用bind后才能連接/收發數據。
UDP在客戶端時可以不調用bind而直接使用recvfrom/sendto來收發數據。?
在客戶端一般是本地地址選擇INETADDR_ANY, 表示所有網絡接口。
?
代碼如下:
#include <stdio.h>;
#include <string.h>;
#include <sys/socket.h>;
#include <netpacket/packet.h>;
#include <net/ethernet.h>;
#include <sys/ioctl.h>;
#include <net/if.h>;
#include <assert.h>;
int
main ()
{
? ?? ???struct sockaddr_ll sll;
? ?? ???int fd;
? ?? ???struct ifreq ifr;
? ?? ???char *dev;
? ?? ???fd = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
? ?? ???dev = "eth0";
? ?? ???strncpy ((char *)ifr.ifr_name, dev, sizeof(ifr.ifr_name));
? ?? ???assert (ioctl (fd, SIOCGIFINDEX, &ifr)==0);
? ?? ???memset (&sll, 0, sizeof(sll));
? ?? ???sll.sll_family = AF_PACKET;
? ?? ???sll.sll_protocol = htons (ETH_P_ALL);
? ?? ???sll.sll_ifindex = ifr.ifr_ifindex;
? ?? ???assert (bind (fd, (struct sockaddr *)&sll, sizeof(sll))==0);
}
?
?
?
?
##############################################################
?
?
?
Windows網絡編程總結(一)
作者: ? Kendiv
出處: ? CSDN.NET ?
關于bind:
INADDR_ANY ? 的具體含義是,綁定到0.0.0.0。此時,對所有的地址都將是有效的,如果系統考慮冗余,采用多個網卡的話,那么使用此種bind,將在所有網卡上進行綁定。在這種情況下,你可以收到發送到所有有效地址上數據包。
例如:
SOCKADDR_IN ? Local;
Local.sin_addr.s_addr ? = ? htonl(INADDR_ANY);
另外一種方式如下:
SOCKADDR_IN ? Local;
hostent* ? thisHost ? = ? gethostbyname( " ");
char* ? ip ? = ? inet_ntoa(*(struct ? in_addr ? *)*thisHost-> h_addr_list);
Local.sin_addr.s_addr ? = ? inet_addr(ip);
在這種方式下,將在系統中當前第一個可用地址上進行綁定。在多網卡的環境下,可能會出問題。
最常見的方式:
const ? char ? LocalIP[] ? = ? "192.168.0.100 ";
SOCKADDR_IN ? Local;
Local.sin_addr.s_addr ? = ? inet_addr(LocalIP);
bind(socket, ? (LPSOCKADDR)&Local, ? sizeof(SOCKADDR_IN)
bind的安全問題:
如果你在bind時,使用了INADDR_ANY那么,你將可以在所有有效的地址上進行監聽,但是Socket有一個特性:可在同一端口上綁定多個Socket。
讓我們看看下面的情況:假設你的系統只有一個IP:192.168.0.100,你希望bind到4096端口。對于下面的兩種bind,當數據包到達時,誰會接收到呢?
Local.sin_addr.s_addr ? = ? htonl(INADDR_ANY);
Local.sin_addr.s_addr ? = ? inet_addr(“192.168.0.100”);
WinSocke庫是這樣處理的:誰綁定的最明確,誰獲取數據包。顯然,第二種bind將獲取到達的數據包。如果避免這種情況呢?使用SO_EXECLUSINEADDRUSE選項。需要注意的是,此選項在Windows ? NT ? 4 ? Service ? Pack ? 4以后(包括SP4)才可以使用。
示例代碼:
#ifndef ? SO_EXECLUSINEADDRUSE
#define ? SO_EXECLUSINEADDRUSE ? ((int)(~SO_REUSEADDR))
#endif
SOCKADDR_IN ? Local;
BOOL ? val ? = ? TRUE;
Local. ? sin_family ? = ? AF_INET;
Local. ? sin_port ? = ? htons(4096);
Local.sin_addr.s_addr ? = ? htonl(INADDR_ANY);
setsocketopt(socket,
SOL_SOCKET,
SO_EXECLUSINEADDRUSE,
(char*)&val,
sizeof(val));
bind(socket, ? (LPSOCKADDR)&Local, ? sizeof(SOCKADDR_IN)
總結
以上是生活随笔為你收集整理的socket通过多网卡收发数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: socket开发:一台服务器同一端口同时
- 下一篇: centos7下升级cmake,很简单