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

WSAIoctl SIO_GET_BROADCAST_ADDRESS issue.

CRodrig
Principiante
1.579 Vistas

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 Respuestas
Paul_Curtis
Colaborador Valioso I
1.579 Vistas

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().

CRodrig
Principiante
1.579 Vistas

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.

Paul_Curtis
Colaborador Valioso I
1.579 Vistas

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.

Responder