2010-10-22 12 views
24

मेरा एप्लिकेशन CentOS 5.5 पर चल रहा है। मैं रॉ सॉकेट उपयोग कर रहा हूँ डेटा भेजने के लिए:विशिष्ट इंटरफ़ेस को कच्चे सॉकेट को कैसे बांधें

sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 
if (sd < 0) { 
    // Error 
} 
const int opt_on = 1; 
rc = setsockopt(m_SocketDescriptor, IPPROTO_IP, IP_HDRINCL, &opt_on, sizeof(opt_on)); 
if (rc < 0) { 
    close(sd); 
    // Error 
} 
struct sockaddr_in sin; 
memset(&sin, 0, sizeof(sin)); 
sin.sin_family = AF_INET; 
sin.sin_addr.s_addr = my_ip_address; 

if (sendto(m_SocketDescriptor, DataBuffer, (size_t)TotalSize, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) { 
    close(sd); 
    // Error 
} 

मैं विशिष्ट नेटवर्क इंटरफेस को यह सॉकेट कैसे बाध्य कर सकते हैं (जैसे कि eth1)?

+0

आप ऐसा क्यों करना चाहते हैं? आपका प्रोग्राम पोर्टेबिलिटी खो देगा जबतक कि आप सुनिश्चित न हों कि आपकी मशीनों में पूर्वनिर्धारित नामों वाले इंटरफेस होंगे। –

+4

यह एम्बेडेड डिवाइस के लिए है, पोर्टेबिलिटी की आवश्यकता नहीं है। मेरे पास 6 ईथरनेट पोर्ट हैं और मुझे विशिष्ट इंटरफ़ेस – Dima

उत्तर

36
char *opt; 
opt = "eth0"; 
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, 4); 

पहली पंक्ति: अपने चर

दूसरी पंक्ति की स्थापना: प्रोग्राम है जो इंटरफेस

करने के लिए बाध्य करने के लिए बता

तीसरी पंक्ति: सॉकेट sd के लिए सॉकेट विकल्प सेट, उपकरण opt के लिए बाध्य, और चूंकि ऑप्ट चार लम्बाई लंबाई 4 लंबाई के रूप में सेट है।

setsockopt प्रोटोटाइप:

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); 

इसके अलावा, सुनिश्चित करें कि आप socket.h हेडर फाइल

+3

का उपयोग करके डेटा भेजने की आवश्यकता है धन्यवाद, यह काम कर रहा है, लेकिन एक छोटे से संशोधन के साथ: ifreq इंटरफ़ेस; मेमसेट (और इंटरफ़ेस, 0, आकार (इंटरफ़ेस)); strncpy (Interface.ifr_ifrn.ifrn_name, "eth1", IFNAMSIZ); यदि (सेटॉकोपट (एसडी, एसओएल_SOCKET, SO_BINDTODEVICE, और इंटरफ़ेस, आकार (इंटरफ़ेस)) <0) { नज़दीकी (एसडी); // त्रुटि } – Dima

+0

SO_BINDTODEVICE केवल रूट के रूप में चलाने पर ही काम करता है, है ना? (कम से कम लिनक्स पर) – sep332

+0

अजीब ऐसा लगता है कि ifreq संरचना की आवश्यकता होती है, जब सॉकेट (7) कि पारित विकल्प परिवर्तनीय-लंबाई Zstring है ... –

14

जैसा कि पहले उल्लेख शामिल करना, ऐसा करने का सही बात struct ifreq का उपयोग इंटरफ़ेस नाम निर्दिष्ट करने के लिए है। मेरा कोड नमूना यहाँ है।

#define SERVERPORT 5555 
... 
struct ifreq ifr; 


/* Create the socket */ 
sd = socket(AF_INET, SOCK_STREAM, 0); 
if (sd < 0) 
{ 
    printf("Error in socket() creation - %s", strerror(errno)); 
} 

/* Bind to eth1 interface only - this is a private VLAN */ 
memset(&ifr, 0, sizeof(ifr)); 
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1"); 
if ((rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) < 0) 
{ 
    perror("Server-setsockopt() error for SO_BINDTODEVICE"); 
    printf("%s\n", strerror(errno)); 
    close(sd); 
    exit(-1); 
} 

/* bind to an address */ 
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in)); 
serveraddr.sin_family = AF_INET; 
serveraddr.sin_port = htons(SERVERPORT); 
serveraddr.sin_addr.s_addr = inet_addr("9.1.2.3"); 

int rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); 

मैं भी है कि जोड़ने के लिए एक सुरक्षा के नजरिए से, जबकि यह एक अंतरफलक के लिए सॉकेट बाध्य करने के लिए अच्छा है चाहते हैं, यह भावना सुनने के आईपी पते के रूप में INADDR_ANY उपयोग करने के लिए नहीं है। ऐसा करने से पोर्ट सभी नेटवर्क इंटरफेस पर नेटस्टैट में खुल जाएगा।

Proto Recv-Q Send-Q Local Address Foreign Address State  User Inode  PID/Program name 
tcp 0  0  0.0.0.0:5555  0.0.0.0:*   LISTEN 0 210898  26996/myserver 

इसके बजाय, मैंने इंटरफ़ेस (एक निजी वीएलएएन) का उपयोग करने के लिए विशिष्ट आईपी पता निर्दिष्ट किया है। इसने नेटस्टैट आउटपुट को भी ठीक किया:

Proto Recv-Q Send-Q Local Address Foreign Address State  User Inode  PID/Program name 
tcp 0  0  9.1.2.3:5555  0.0.0.0:*   LISTEN 0 210898  26996/myserver 
+1

यह कहां निर्दिष्ट किया गया है कि आप 'struct ifreq' का उपयोग करते हैं? मेरा मैन पेज कहता है " पास विकल्प एक परिवर्तनीय-लंबाई नल-टर्मिनेटेड इंटरफ़ेस नाम स्ट्रिंग है" – Bryan

+3

आपके द्वारा सुझाई गई समस्या (SOCK_STREAM सॉकेट के लिए INADDR_ANY) मूल पोस्टर के लिए नहीं होती है, जो SOCK_RAW का उपयोग कर रहा था। –

संबंधित मुद्दे