TCP/IP connection on a specific interface
Use the bind()
function to bind the socket to either 192.168.1.3
or 192.168.1.2
before calling connect()
, ConnectEx()
, or WSAConnect()
. That tells the socket which specific interface to use for the outgoing connection. For example:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in localaddr = {0};
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = inet_addr("192.168.1.3");
bind(s, (sockaddr*)&localaddr, sizeof(localaddr));
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = inet_addr("192.168.1.4");
remoteaddr.sin_port = 12345; // whatever the server is listening on
connect(s, (sockaddr*)&remoteaddr, sizeof(remoteaddr));
Alternatively:
addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;
addrinfo *localaddr = NULL;
getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
freeaddrinfo(localaddr);
addrinfo remotehints = {0};
remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
remotehints.ai_family = AF_INET;
remotehints.ai_socktype = SOCK_STREAM;
remotehints.ai_protocol = IPPROTO_TCP;
addrinfo *remoteaddr = NULL;
getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
freeaddrinfo(remoteaddr);
Using a specific network interface for a socket in windows
(Ok second time lucky..)
FYI there's another question here perform connect() on specific network adapter along the same lines...
According to The Cable Guy
Windows XP and Windows Server® 2003
use the weak host model for sends and
receives for all IPv4 interfaces and
the strong host model for sends and
receives for all IPv6 interfaces. You
cannot configure this behavior. The
Next Generation TCP/IP stack in
Windows Vista and Windows Server 2008
supports strong host sends and
receives for both IPv4 and IPv6 by
default on all interfaces except the
Teredo tunneling interface for a
Teredo host-specific relay.
So to answer your question (properly, this time) in Windows XP and Windows Server 2003 IP4 no, but for IP6 yes. And for Windows Vista and Windows 2008 yes (except for certain circumstances).
Also from http://www.codeguru.com/forum/showthread.php?t=487139
On Windows, a call to bind() affects
card selection only incoming traffic,
not outgoing traffic. Thus, on a
client running in a multi-homed system
(i.e., more than one interface card),
it's the network stack that selects
the card to use, and it makes its
selection based solely on the
destination IP, which in turn is based
on the routing table. A call to bind()
will not affect the choice of the card
in any way.It's got something to do with
something called a "Weak End System"
("Weak E/S") model. Vista changed to a
strong E/S model, so the issue might
not arise under Vista. But all prior
versions of Windows used the weak E/S
model.With a weak E/S model, it's the
routing table that decides which card
is used for outgoing traffic in a
multihomed system.See if these threads offer some
insight:"Local socket binding on multihomed
host in Windows XP does not work" at
http://www.codeguru.com/forum/showthread.php?t=452337"How to connect a port to a specified
Networkcard?" at
http://www.codeguru.com/forum/showthread.php?t=451117.
This thread mentions the
CreateIpForwardEntry() function, which
(I think) can be used to create an
entry in the routing table so that all
outgoing IP traffic with a specified
server is routed via a specified
adapter."Working with 2 Ethernet cards" at
http://www.codeguru.com/forum/showthread.php?t=448863"Strange bind behavior on multihomed
system" at
http://www.codeguru.com/forum/showthread.php?t=452368
Hope that helps!
QTCPSocket - How to force connection to specific network when host has connection to seperate networks
You can select the outgoing interface to use by calling bind()
with your interfaces address first. This will select your outgoing address to use.
See the documentation for the bind function:
For TCP sockets, this function may be used to specify which interface to use for an outgoing connection, which is useful in case of multiple network interfaces.
I threw together a very simple demo for you:
Its all running locally. This is the servers main.cpp:
#include <QCoreApplication>
#include <QTcpServer>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTcpServer serv;
QObject::connect(&serv, &QTcpServer::newConnection, [](){
qDebug() << "New connection!";
});
qDebug() << serv.listen(QHostAddress("192.168.x.y"), 1337);
return a.exec();
}
And this is the clients main.cpp:
#include <QCoreApplication>
#include <QDebug>
#include <QTcpSocket>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTcpSocket s;
qDebug() << s.bind(QHostAddress("127.0.0.1"));
s.connectToHost(QHostAddress("192.168.x.y"), 1337);
return a.exec();
}
By calling bind
we tell the client to send packets using the local interface, but as the server only listens to my wifi interface 192.168.x.y the connection will fail. If you now change the following line:
qDebug() << s.bind(QHostAddress("127.0.0.1"));
as such:
qDebug() << s.bind(QHostAddress("192.168.x.y"));
You will see that the server will recieve the connection, as we explicitly selected this interface to send from.
However, the operating system should select the correct interface for you (meaning in the demo: by not calling bind you should get a connection). If that does not happen you have a different issue.
To get a list of all available interfaces you can use QNetworkInterface::allInterfaces()
which will grant you access to everything might you need to know.
Dial with a specific address / interface ? Golang
When you pull the address from an interface, it's of type *net.IPnet
wrapped in a net.Addr
interface, which contains an address and netmask NOT an address and port. You can use the IP address, however, you have to create a new TCPAddr
after asserting it as a *net.IPnet
ief, err := net.InterfaceByName("eth1")
if err !=nil{
log.Fatal(err)
}
addrs, err := ief.Addrs()
if err !=nil{
log.Fatal(err)
}
tcpAddr := &net.TCPAddr{
IP: addrs[0].(*net.IPNet).IP,
}
Related Topics
Serializing Opencv Mat_<Vec3F>
Critique My Non-Intrusive Heap Debugger
How to Do Input Validation in C++ with Cin
Why "Initializer-String for Array of Chars Is Too Long" Compiles Fine in C & Not in C++
Catching "Stack Overflow" Exceptions in Recursive C++ Functions
Using Std:Fstream How to Deny Access (Read and Write) to the File
How to Show Enter Password in the Form of Asterisks(*) on Terminal
Convert String with Explicit Escape Sequence into Relative Character
Why Can't I Do Polymorphism with Normal Variables
Address-Of Operator (&) VS Reference Operator(&)
How to Declare an Array of Objects Whose Class Has No Default Constructor
Training Custom Svm to Use with Hogdescriptor in Opencv
Why Is the Size of Array as a Constant Variable Not Allowed in C But Allowed in C++
What Is the Meaning of Auto When Using C++ Trailing Return Type
How to Create a Temporary Directory in C++