5
« Poslední příspěvek od Jan Novotný kdy 06. 11. 2024, 22:05:00 »
Dobrý den,
prosím, potřebuji poradit, jak správně použít bind socketu na konkrétní síťovou kartu v linuxu.
Jde o tento případ: Linux se 3 síťovkami, default gateway je směrem za síťovkou 1. Adresa serveru 192.168.1.55.
Klientské síťovky 192.168.1.51, 192.168.1.52, 192.168.1.53.
Klient ve výchozím stavu odesílá / přijímá data v pořádku přes síťovku 1.
Odesílat / přijímat potřebuji přes síťovku 3 (enp0s8).
Musím tedy použít bind to device.
setsockopt(udpSocket, SOL_SOCKET, SO_BINDTODEVICE, localEthDeviceName
Pokud nabinduji socket na enp0s8, je vidět v tcpdump, že klient data odešle přes síťovku 3 a také přijímá přes síťovku 3, ale nastává problém, že recvfrom() nezíská ze socketu žádná data a tedy odpověď do aplikace nedorazí.
Nevíte, čím to může být, proč recvfrom v případě bindu na síťovku žádná data nedostane?
Jak bych měl bind správně použít?
Kód jednoduchého UDP klienta přikládám níže.
Děkuju moc za radu.
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <cerrno>
using namespace std;
int main(int argc, char** argv) {
#define MAXBUF 1024
int udpSocket, returnStatus, addrlen;
struct sockaddr_in udpClient, udpServer;
char buf[MAXBUF];
string message = getSendMessage();
string localEthDeviceName = "enp0s8";
/* create a socket */
if ((udpSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
fprintf(stderr, "Could not create a socket!\n");
return(1);
}else{
printf("Socket created.\n");
}
if (setsockopt(udpSocket, SOL_SOCKET, SO_BINDTODEVICE, localEthDeviceName.c_str(), static_cast<socklen_t>(strlen(localEthDeviceName.c_str()))) == -1) {
close(udpSocket);
return 1;
}
/* client address */
string localIp = "192.168.1.51";
udpClient.sin_family = AF_INET;
udpClient.sin_addr.s_addr = inet_addr(localIp.c_str());
udpClient.sin_port = htons(5065);
returnStatus = bind(udpSocket, (struct sockaddr*)&udpClient, sizeof(udpClient));
if (returnStatus == 0) {
fprintf(stderr, "Bind completed!\n");
}
else {
fprintf(stderr, "Could not bind to address!\n");
close(udpSocket);
return(1);
}
/* server address */
string serverIp = "192.168.1.55";
udpServer.sin_family = AF_INET;
udpServer.sin_addr.s_addr = inet_addr(serverIp.c_str());
udpServer.sin_port = htons(5060);
returnStatus = static_cast<int>(sendto(udpSocket, message.c_str(), strlen(message.c_str()) + 1, 0, (struct sockaddr*)&udpServer, sizeof(udpServer)));
if (returnStatus == -1) {
fprintf(stderr, "Could not send message!\n");
}
else {
/* message sent: look for confirmation */
addrlen = sizeof(udpServer);
returnStatus = static_cast<int>(recvfrom(udpSocket, buf, MAXBUF, 0, (struct sockaddr*)&udpServer, reinterpret_cast<socklen_t*>(& addrlen)));
if (returnStatus <= 0) {
fprintf(stderr, "Didn't get any response: %s\n", strerror(errno));
}
else {
buf[returnStatus] = 0;
printf("Received: %s\n", buf);
}
}
return 0;
}