Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29241 Discussions

WSAIoctl SIO_GET_BROADCAST_ADDRESS issue.

CRodrig
Beginner
1,566 Views

Intel Forum,

I am using UDP sockets in my application.

I would like to extract the Broadcast Address of my Windows 7 system so
as to pass the information to the <sendto> function.

Source Code:

      INTEGER(DWORD) disport, disend_fd, disrcv_fd
      INTEGER(DWORD) dwBytesRet
      INTEGER(DWORD) istat
c
      INTEGER(DWORD) :: sockfd = INVALID_SOCKET
      INTEGER(DWORD) :: status = 0
c
      logical(DWORD) :: boptval = .TRUE.
c
      INTEGER(DWORD), PARAMETER :: success = 0
c
c  -- Initialize Winsock v2.
c
      INTEGER(DWORD), PARAMETER ::  winsock_v2_2 = X'202'
c
      TYPE(T_WSADATA) wsaInfo
c
      TYPE(T_OVERLAPPED) lpOverlapped
c
      TYPE(T_SOCKADDR_IN) :: send_addr
      TYPE(T_SOCKADDR_IN) :: bcast_addr
c
      istat = 0
c
      status = WSAStartup(winsock_v2_2, wsaInfo)
c
      if (status .ne. success) then  
        print *, 'WSAStartup - Error Code = ', status
c
        istat = 1
        return
      endif
c
c     -------------------
c     -- Send segment.
c     -------------------
c
c   - Configure socket to support User Datagram Protocol (UDP) for Internet address family (AF_INET).
c
      sockfd = Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
      istat =  WSAGetLastError()
c
      if (sockfd .eq. INVALID_SOCKET) then
        print *, 'Socket - Error Code = ', istat
c
        status = WSACleanup()
        istat = 1
        return
      endif
c
      status = setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,%REF(boptval),
     &                    sizeof(boptval))
      istat =  WSAGetLastError()
c
      if (status .eq. SOCKET_ERROR) then  
        print *, 'setsockopt - Error Code = ', istat
c
        istat = 1
        return
      endif
c
      status = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,%REF(boptval),
     &                    sizeof(boptval))
      istat =  WSAGetLastError()
c
      if (status .eq. SOCKET_ERROR) then  
        print *, 'setsockopt - Error Code = ', istat
c
        istat = 1
        return
      endif
c
c   - Connect to socket.
c
      call ZeroMemory(loc(send_addr), sizeof(send_addr))
c
      send_addr%sin_family      = INT2(AF_INET)
      send_addr%sin_port        = htons(INT2(disport))
      send_addr%sin_addr%s_addr = htonl(INADDR_ANY)
c
c   - WSAIoctl function populates the output buffer with a bcast_addr structure
c     containing a suitable broadcast address for use with sendto function.
c     [ Not supported for IPv6 sockets (returns WSAENOPROTOOPT). ]
c
      call ZeroMemory(loc(bcast_addr), sizeof(bcast_addr))
      call ZeroMemory(loc(lpOverlapped), sizeof(lpOverlapped))
c
      status = WSAIoctl(sockfd,
     &                  SIO_GET_BROADCAST_ADDRESS,
     &                  NULL,
     &                  0,
     &                  %REF(bcast_addr),
     &                  sizeof(bcast_addr),
     &                  dwBytesRet,
     &                  %REF(lpOverlapped),
     &                  NULL)
      istat =  WSAGetLastError()
c
      if (status .eq. SOCKET_ERROR) then
        print *, "WSAIoctl(SIO_GET_BROADCAST_ADDRESS) error code = ",
     &            istat
c
        istat = 1
        return
      else
        bcast_addr%sin_port = htons(INT2(disport))
c
        print *, "Broadcast address is: ",
     &            inet_ntoa(bcast_addr.sin_addr)
      endif
c
      disend_fd = sockfd

I have executed the code and everything seems to be working fine. I am send UDP packets from my Windows 7 system
over the network and am receiving UDP packets on another application running on my CentOS 6.5 system.

Question:

1). Every time I execute the code and print the Broadcast address, the Broadcast address changes and
    the value does not make sense in relation to my IP addressing scheme.

Am I implementing the WSAIoctl function correctly?

Thanks in advance.

0 Kudos
3 Replies
Paul_Curtis
Valued Contributor I
1,566 Views

Your code looks ok (altho I use LOC() instead of %REF(), didn't know you could do that).  My codes open sockets and exchange packets, UDP or TCP depending on what is being talked to, without using WSAIoctl(): simply open a socket for the target IP address and packet type, and then use its handle with WSASend() and WSARecv().  I don't follow why you would need a broadcast address, as the socket() function automatically incorporates its host IP address when the socket is created.  You can find the IP addresses of all installed NICs using GetAdaptersInfo().

0 Kudos
CRodrig
Beginner
1,566 Views

Paul,

Thanks for your response.

What advantage/benefit does the WSASend() and WSARecv() provide over the generic send() / sendto()

and recv() / recvfrom() functions?

Could you enlighten me on the purpose/use of overlapped sockets. Can you provide an example on how you use

the WSASend/WSARecv functions in your code?

Thanks again.

0 Kudos
Paul_Curtis
Valued Contributor I
1,566 Views

MSDN has more (and better) to say on overlapped sockets, but the general idea is that using an overlap structure with a completion event allows the communications overhead to be handed off to Windows, so that your program does not become serialized and hang during the turnaround time for query/response packets from your targeted server. This technique also permits you to have many communications channels open simultaneously. You create the socket, send a packet, go into receive mode waiting for the response, but the wait time is transparent to your program (your user interface is still responsive, for example), and Windows sends you a message (ie, sets the completion event) when the response packet has been received.  I go one step further and isolate all communications within a separate worker thread which signals the main program when each communications exercise completes.

Take a look at the attached file, abstracted from a large program, which implements Winsock communications.

0 Kudos
Reply