[질문]네트워크 카드가 두개 이상일 때 UDP 서버소켓 프로그래밍

renige의 이미지

안녕하십니까..
봄이군요.. 아주 날씨가 좋네요..

네트워크 카드를 두개 이상 쓰는 프로그램을 만들고자 합니다.
UDP 서버소켓을 생싱시 자신의 주소 정보를 sockaddr_in 구조체에 저장하고 bind를 하는데 하나인 경우에는
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
이런 식으로 하면 되는데...
네트워크 카드가 두개인 경우 각 네트워크 카드에 하나씩 UDP 서버 소켓을 생성 시켜야 함으로
my_addr.sin_addr.s_addr = inet_addr("210.115.43.181");
이런 식으로야 되는데 이렇게 할경우
실행까지는 다 되는데, 데이터를 받지를 못합니다.

기본적으로 udp 프로그램에는 이상이 없고 이상한것은
my_addr.sin_addr.s_addr = inet_addr("210.115.43.181");
이 TCP에서는 잘 돌아간다는 것입니다.

아시는 분의 도움을 바람니다. 감사합니다.

 #include <stdio.h> 
    #include <stdlib.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <sys/types.h> 
    #include <netinet/in.h> 
    #include <sys/socket.h> 
    #include <sys/wait.h> 

    #define MYPORT  4950   

    #define MAXBUFLEN 100

    main()
    {
        int sockfd;
        struct sockaddr_in my_addr;    
        struct sockaddr_in their_addr; 
        int addr_len, numbytes;
        char buf[MAXBUFLEN];
	unsigned int yes;
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }

	//setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&yes,sizeof(yes));
		  bzero((char*)&my_addr,sizeof(my_addr));
        my_addr.sin_family = AF_INET;        
        my_addr.sin_addr.s_addr = inet_addr("210.115.43.181"); //--> 이렇게 하면 안되고 TCP에서는 이렇게 하면 되는데..
        //my_addr.sin_addr.s_addr =  htonl(INADDR_ANY); //--> 이렇게 히면 됩니다. 
        my_addr.sin_port = htons(MYPORT);     
        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
                                                                       == -1) {
            perror("bind");
            exit(1);
        }

        addr_len = sizeof(struct sockaddr);
        if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN, 0, \
                           (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }

        printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
        printf("packet is %d bytes long\n",numbytes);
        buf[numbytes] = '\0';
        printf("packet contains \"%s\"\n",buf);

        close(sockfd);
    }
rokmn3309의 이미지

듀얼랜카드를 말씀하시면..
그냥 한개일때랑 동일하게 하시면 되는걸로 아는데..
맥어드레스도 하나로 사용하게 되는데.

다음은 그냥 듀얼랜카드로 동작하는 컴의 /etc/sysconfig/network-scripts/ifcfg-bond0과 ifcfg-eth0,ifcfg-eth1의 정보를 올려 드립니다.

[root@480GT network-scripts]# cat ifcfg-bond0
DEVICE=bond0
USERCTL=no
ONBOOT=yes
BOOTPROTO=none
BROADCAST=192.168.0.255
IPADDR=192.168.0.13
NETMASK=255.255.255.0
NETWORK=192.168.0.0

[root@480GT network-scripts]# cat ifcfg-eth0
DEVICE=eth0
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none

[root@480GT network-scripts]# cat ifcfg-eth1
DEVICE=eth1
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none

그리고 다음은 ifconfig시의 정보입니다.

[root@480GT network-scripts]# ifconfig
bond0     Link encap:Ethernet  HWaddr 00:03:47:B2:59:3C
          inet addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
          RX packets:237 errors:0 dropped:0 overruns:0 frame:0
          TX packets:161 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:20325 (19.8 Kb)  TX bytes:15681 (15.3 Kb)

eth0      Link encap:Ethernet  HWaddr 00:03:47:B2:59:3C
          inet addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:237 errors:0 dropped:0 overruns:0 frame:0
          TX packets:161 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:20325 (19.8 Kb)  TX bytes:15681 (15.3 Kb)
          Interrupt:7

eth1      Link encap:Ethernet  HWaddr 00:03:47:B2:59:3C
          inet addr:192.168.0.13  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
          Interrupt:10 Base address:0x2000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:72 errors:0 dropped:0 overruns:0 frame:0
          TX packets:72 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:5272 (5.1 Kb)  TX bytes:5272 (5.1 Kb)

저도 UDP로 통신하는걸 랜카드 한개일때랑 두개일때랑 만들었지만은..
동일한 프로그램코드로 적용시켰습니다..
이게 답변이 될련지..

renige의 이미지

rokmn3309 님 답변 감사합니다.
그런데 제 경우는 두카드가 다른 ip를 사용하는 경우 입니다. 어떻게 해야 하는 건지. 그렇게 하려면 각 서버 소켓 마다 다른 ip로 bind해야 되는데..
ip두개라면
my_addr.sin_addr.s_addr = INADDR_ANY
이게 아니라
my_addr.sin_addr.s_addr = inet_addr("210.115.43.181");
my_addr1.sin_addr.s_addr = inet_addr("210.115.43.182");

이런 식으로 해야 될것 같은데.. 데이터를 받지를 못하네요..
도움 부탁 드립니다.

dude7853의 이미지

제가 올려주신 코드를 이용해서 테스트 해봤는데
전혀 문제가 없었습니다.
저의 경우 랜카드가 3개 꽃혀있는 PC에서
각각의 IP로 UDP 서버를 구동시키고,
테스트해봤지만, 메세지를 잘 받더군요.
물론 코드에 문제도 없구요.

아마도 테스트 하실때 클라이언트 프로그램을 잘못 작성하신게 아닌가
생각됩니다.

hekimian의 이미지

my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

위의 코드에서 INADDR_ANY의 의미는 특정 포트로의 연결들은 어떤 인터넷 주소로 보내지더라도 이 소켓으로 가게 된다는 의미입니다.
이 방식은 호스트가 여러 인터넷주소를 가지고 있을때 유용한 방법입니다.

라고 쓰여져 있네요. ^^

즉, 위와 같이 구현 하신다면 여러개의 IP(server가 가지고 있는 여러개의 IP)로 들어오는 요청에 대해서 전부 처리 하실수 있습니다.

나를 죽이지 않는 모든 것은 나를 강하게 할 뿐이다.

renige의 이미지

답변 달아 주신 분들 감사 합니다. 여러분들의 글이 저에겐 아주 많은 도움이 되는군요..
하다 보니 궁금한게 또 생겨서 글을 씁니다.
소켓이 여러개 있고 각 소켓을 초기화 시킬때 소켓을 구분할 수 있는 name, ip address, port를 파라미터로 넘겨주고 소켓을 초기화 시킵니다.
그리고 name, ip, port, 소켓을 구조체 배열로 만들어서, 소켓에서 데이터가 들어 올경우 같이 묶여진 ip를 보고 어느 네트워크 카드에서 온것인지를 구분하고자 합니다.(물론 포트로 구분하면 쉽겠지만,)

ip로 서버 소켓을 초기화 시켜서 ip와 소켓을 구조체로 묶어서 ip로 소켓을 구분하는 방법을 알고 싶습니다.

그러러면 결국 파라미터로 ip, name, port를 넘겨줘서
my_addr.sin_addr.s_addr = inet_addr("210.115.43.181");
이런 형식으로 ip를 바인드 시켜서 초기화시 구조체에 name, ip, port,소켓 정보를 넣어야 되는데. 바인드는 위와 같이 sockaddr_in 구조체에 ip를 넣고, UDP 클라이언트에서 서버의 ip를 210.115.43.181 으로 해 주고 바인드한 후 클라이언트에서 데이터를 보내면 (유니캐스트)가는데 , 210.115.43.255바인드를 하고 클라이언트가 브로드 캐스팅으로 해 주면 데이터가 안가고 서버 소켓 측에 my_addr.sin_addr.s_addr = htonl(INADDR_ANY); 로 해주면 데이터가 전송 됩니다.
결국 문제는 ip를 넘겨줘서 이걸로 sockaddr_in 구조체를 채우고 바인드 하는건데... 이게 잘 안되는거 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.