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

Winsock?

gib
New Contributor II
3,340 Views
Steve, I saw a comment you made on c.l.f about a winsock module in IVF. Where can I find info about this? The docs don't seem to have anything.

Thanks
Gib
0 Kudos
1 Solution
Paul_Curtis
Valued Contributor I
3,340 Views
Quoting - gib
Hi Paul,
I'm looking into possible ways of communicating data asynchronously between an executing Fortran program and a Python program that will handle the GUI duties. For portability I've decided to adopt the approach where the Fortran is built as a library (DLL or .so), and input data is passed in files. I'm not sure what method would be best for displaying on-the-fly results in the Python master program, but using sockets is one option. If this seems to be a good way to go I would be very interested in your code.

This might be a good place to ask whether someone thinks another method would be preferable, e.g. writing and reading from a file.

I like the flexibility of using sockets. Looking ahead, the socket approach would enable server-based execution of the Fortran engine. The Python could be distributed to users, and the model could be run on a powerful multicore server. This assumes that I'm able to interest others in using the model, of course.

The att. file has been carved out of a large program, and hastily modified to be roughly stand-alone with dependences on other objects and code hopefully eliminated; at any rate, this may serve as a quick guide on setting up socket-based communications (it does work extremely well). This module uses ReadFile/WriteFile once a socket has been set up, and it may be that the more specialized functions WSARecv() and WSASend() might also work, maybe better.

Although you didn't ask, your stated project outline leads me to suggest that you can easily build complete Win32 gui features entirely in Fortran, thereby eliminating an architectural approach which looks to be hugely complex right from the start. Good luck.

View solution in original post

0 Kudos
16 Replies
Steven_L_Intel1
Employee
3,340 Views

It's one of the Win32 modules. Actually, two of them: wsock32.mod and ws2_32.mod. You can find the sources to these in the compiler's Include folder. We don't have any samples that use these.
0 Kudos
Paul_Curtis
Valued Contributor I
3,340 Views
Quoting - gib
Steve, I saw a comment you made on c.l.f about a winsock module in IVF. Where can I find info about this? The docs don't seem to have anything.

Thanks
Gib

Gib,
What do you want to do here? I have written a set of Winsock routines for ethernet communications, which use the Win32 API functions in WS2_32.f90 (interface module included with IVF), and allow you to open a socket to an IP address and read and write packets.
0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis

Gib,
What do you want to do here? I have written a set of Winsock routines for ethernet communications, which use the Win32 API functions in WS2_32.f90 (interface module included with IVF), and allow you to open a socket to an IP address and read and write packets.
Hi Paul,
I'm looking into possible ways of communicating data asynchronously between an executing Fortran program and a Python program that will handle the GUI duties. For portability I've decided to adopt the approach where the Fortran is built as a library (DLL or .so), and input data is passed in files. I'm not sure what method would be best for displaying on-the-fly results in the Python master program, but using sockets is one option. If this seems to be a good way to go I would be very interested in your code.

This might be a good place to ask whether someone thinks another method would be preferable, e.g. writing and reading from a file.

I like the flexibility of using sockets. Looking ahead, the socket approach would enable server-based execution of the Fortran engine. The Python could be distributed to users, and the model could be run on a powerful multicore server. This assumes that I'm able to interest others in using the model, of course.
0 Kudos
gib
New Contributor II
3,340 Views

It's one of the Win32 modules. Actually, two of them: wsock32.mod and ws2_32.mod. You can find the sources to these in the compiler's Include folder. We don't have any samples that use these.
Ah, I see. Thanks Steve.
0 Kudos
Paul_Curtis
Valued Contributor I
3,341 Views
Quoting - gib
Hi Paul,
I'm looking into possible ways of communicating data asynchronously between an executing Fortran program and a Python program that will handle the GUI duties. For portability I've decided to adopt the approach where the Fortran is built as a library (DLL or .so), and input data is passed in files. I'm not sure what method would be best for displaying on-the-fly results in the Python master program, but using sockets is one option. If this seems to be a good way to go I would be very interested in your code.

This might be a good place to ask whether someone thinks another method would be preferable, e.g. writing and reading from a file.

I like the flexibility of using sockets. Looking ahead, the socket approach would enable server-based execution of the Fortran engine. The Python could be distributed to users, and the model could be run on a powerful multicore server. This assumes that I'm able to interest others in using the model, of course.

The att. file has been carved out of a large program, and hastily modified to be roughly stand-alone with dependences on other objects and code hopefully eliminated; at any rate, this may serve as a quick guide on setting up socket-based communications (it does work extremely well). This module uses ReadFile/WriteFile once a socket has been set up, and it may be that the more specialized functions WSARecv() and WSASend() might also work, maybe better.

Although you didn't ask, your stated project outline leads me to suggest that you can easily build complete Win32 gui features entirely in Fortran, thereby eliminating an architectural approach which looks to be hugely complex right from the start. Good luck.
0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis
The att. file has been carved out of a large program, and hastily modified to be roughly stand-alone with dependences on other objects and code hopefully eliminated; at any rate, this may serve as a quick guide on setting up socket-based communications (it does work extremely well). This module uses ReadFile/WriteFile once a socket has been set up, and it may be that the more specialized functions WSARecv() and WSASend() might also work, maybe better.

Although you didn't ask, your stated project outline leads me to suggest that you can easily build complete Win32 gui features entirely in Fortran, thereby eliminating an architectural approach which looks to be hugely complex right from the start. Good luck.
Thanks a lot Paul, that's great!

In reply to your comment, if I expect others to use this program (and that's the main reason for creating a GUI) I can't stay in the Windows world. Most biologists, my target audience, use Macs. I am trying to plot the course ahead such that the code will be completely platform-neutral, well, able to run on Windows, Linux and OSX. Python runs everywhere, and then there's gfortran or G95 for places where IVF code can't go.
0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis

The att. file has been carved out of a large program, and hastily modified to be roughly stand-alone with dependences on other objects and code hopefully eliminated; at any rate, this may serve as a quick guide on setting up socket-based communications (it does work extremely well). This module uses ReadFile/WriteFile once a socket has been set up, and it may be that the more specialized functions WSARecv() and WSASend() might also work, maybe better.

Although you didn't ask, your stated project outline leads me to suggest that you can easily build complete Win32 gui features entirely in Fortran, thereby eliminating an architectural approach which looks to be hugely complex right from the start. Good luck.
Hi Paul,
After fixing a couple of typos and adding 'use ifwin' I got rid of most of the compilation errors. But I still get these messages:
1>D:FortranCodewinsock_example.f90(81): error #6405: The same named entity from different modules and/or program units cannot be referenced. [WSASTARTUP]
1>D:FortranCodewinsock_example.f90(86): error #6405: The same named entity from different modules and/or program units cannot be referenced. [WSACLEANUP]
1>D:FortranCodewinsock_example.f90(125): error #6405: The same named entity from different modules and/or program units cannot be referenced. [SOCKET]
1>D:FortranCodewinsock_example.f90(127): error #6405: The same named entity from different modules and/or program units cannot be referenced. [SOCKET]
1>D:FortranCodewinsock_example.f90(136): error #6405: The same named entity from different modules and/or program units cannot be referenced. [SETSOCKOPT]
1>D:FortranCodewinsock_example.f90(172): error #6405: The same named entity from different modules and/or program units cannot be referenced. [HTONS]
1>D:FortranCodewinsock_example.f90(175): error #6405: The same named entity from different modules and/or program units cannot be referenced. [CONNECT]
1>D:FortranCodewinsock_example.f90(202): error #6405: The same named entity from different modules and/or program units cannot be referenced. [SHUTDOWN]
1>D:FortranCodewinsock_example.f90(203): error #6405: The same named entity from different modules and/or program units cannot be referenced. [CLOSESOCKET]
1>D:FortranCodewinsock_example.f90(328): error #6405: The same named entity from different modules and/or program units cannot be referenced. [SHUTDOWN]
1>D:FortranCodewinsock_example.f90(330): error #6405: The same named entity from different modules and/or program units cannot be referenced. [CLOSESOCKET]
1>D:FortranCodewinsock_example.f90(346): error #6405: The same named entity from different modules and/or program units cannot be referenced. [WSAGETLASTERROR]

I don't know what this means. Perhaps I should be doing something other than using ifwin. Is there a build setting that I'm missing, some library to link?
0 Kudos
Paul_Curtis
Valued Contributor I
3,340 Views
IFWIN is just a set of USE statements for the various Win32 interface modules, which track their Windows counterparts. In this case (as the code says) you need to USE ws2_32, and not wsock32 which is part of the IFWIN collection. Here is what I do in the main program from which this winsock module was extracted:

[cpp]!   these are the contents of ifwin, omitting wsock32;
!   the module winsock.f90 USEs ws2_32.f90 instead,
!   and we thus need to avoid conflicts with wsock32.f90
USE advapi32
USE comdlg32
USE ifwbase
USE gdi32
USE kernel32
!use lz32
!use mpr      ! WNet connection APIs, not used by this program
USE shell32
USE user32
!use version
!use winmm    ! Windows multimedia APIs, not used by this program
USE winspool

!   Win32 types and defines
USE ifwinty
[/cpp]

0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis
IFWIN is just a set of USE statements for the various Win32 interface modules, which track their Windows counterparts. In this case (as the code says) you need to USE ws2_32, and not wsock32 which is part of the IFWIN collection. Here is what I do in the main program from which this winsock module was extracted:

[cpp]!   these are the contents of ifwin, omitting wsock32;
! the module winsock.f90 USEs ws2_32.f90 instead,
! and we thus need to avoid conflicts with wsock32.f90
USE advapi32
USE comdlg32
USE ifwbase
USE gdi32
USE kernel32
!use lz32
!use mpr ! WNet connection APIs, not used by this program
USE shell32
USE user32
!use version
!use winmm ! Windows multimedia APIs, not used by this program
USE winspool

! Win32 types and defines
USE ifwinty
[/cpp]

Thanks, that works. I'm very unfamiliar with this W32 stuff.

Cheers
Gib
0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis
IFWIN is just a set of USE statements for the various Win32 interface modules, which track their Windows counterparts. In this case (as the code says) you need to USE ws2_32, and not wsock32 which is part of the IFWIN collection. Here is what I do in the main program from which this winsock module was extracted:

[cpp]!   these are the contents of ifwin, omitting wsock32;
! the module winsock.f90 USEs ws2_32.f90 instead,
! and we thus need to avoid conflicts with wsock32.f90
USE advapi32
USE comdlg32
USE ifwbase
USE gdi32
USE kernel32
!use lz32
!use mpr ! WNet connection APIs, not used by this program
USE shell32
USE user32
!use version
!use winmm ! Windows multimedia APIs, not used by this program
USE winspool

! Win32 types and defines
USE ifwinty
[/cpp]

Sorry to bother you, Paul, but the info available for winsock and IVF is very limited, as I'm sure you discovered. I haven't been able to figure out how to supply the host address wp%ip_addr:
TYPE(T_IN_ADDR) :: ip_addr ! server IP address u_long
I presume this involves gethostbyname() or gethostbyaddr(), but all my attempts with these have failed to return anything other than 0. Can you show some code that does this?

Thanks
Gib

I found inet_addr(), which I believe does what I want, since I now can call Set_Winsock_Port() and get a handle, so presumably I have created a UDP client socket. For some reason it doesn't work get with the TCP protocol.

0 Kudos
Paul_Curtis
Valued Contributor I
3,340 Views
Quoting - gib
Sorry to bother you, Paul, but the info available for winsock and IVF is very limited, as I'm sure you discovered. I haven't been able to figure out how to supply the host address wp%ip_addr:
TYPE(T_IN_ADDR) :: ip_addr ! server IP address u_long
I presume this involves gethostbyname() or gethostbyaddr(), but all my attempts with these have failed to return anything other than 0. Can you show some code that does this?

Thanks
Gib

I found inet_addr(), which I believe does what I want, since I now can call Set_Winsock_Port() and get a handle, so presumably I have created a UDP client socket. For some reason it doesn't work get with the TCP protocol.


The following utility function makes clear how ip address elements are packaged into an I*4:
[cpp]INTEGER FUNCTION ip_addr_to_string (ipa, string) RESULT (nc)
    IMPLICIT NONE
    INTEGER, INTENT(IN)             :: ipa
    CHARACTER(LEN=*), INTENT(OUT)   :: string
    
    WRITE (string, '(3(I3,"."),I3)')       IAND(ipa, Z'000000FF'),       &
                                     ISHFT(IAND(ipa, Z'0000FF00'),  -8), &
                                     ISHFT(IAND(ipa, Z'00FF0000'), -16), &
                                     ISHFT(IAND(ipa, Z'FF000000'), -24)
    nc = leftpack(string)
END FUNCTION ip_addr_to_string
[/cpp]
Here are some wrapper functions to access an ip address control in a dialog:
[cpp]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! IP Address control functions
!

SUBROUTINE IPAddressSetAddress (hwnd, controlId, addr)
    IMPLICIT NONE
    INTEGER, INTENT(IN)                 :: hwnd
    INTEGER, INTENT(IN)                 :: controlId
    TYPE(T_IN_ADDR),INTENT(INOUT)       :: addr
    INTEGER						        :: j
    
	j = SendControlMessage (hwnd, controlId, IPM_SETADDRESS, 0, addr%s_addr)

END SUBROUTINE IPAddressSetAddress


SUBROUTINE IPAddressGetAddress (hwnd, controlId, addr)
    IMPLICIT NONE
    INTEGER(HANDLE), INTENT(IN)         :: hwnd
    INTEGER, INTENT(IN)                 :: controlId
    TYPE(T_IN_ADDR), INTENT(INOUT)      :: addr
    INTEGER						        :: j
    
	j = SendControlMessage (hwnd, controlId, IPM_GETADDRESS, 0, LOC(addr%s_addr))

[/cpp]



Also, on input you need to tranpose the integer format:
[cpp]!   transpose the little-endian intel format to big-endian ip format
inad%s_addr = ntohl(ip_addr%s_addr)
[/cpp]

0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis

The following utility function makes clear how ip address elements are packaged into an I*4:
[cpp]INTEGER FUNCTION ip_addr_to_string (ipa, string) RESULT (nc)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ipa
CHARACTER(LEN=*), INTENT(OUT) :: string

WRITE (string, '(3(I3,"."),I3)') IAND(ipa, Z'000000FF'), &
ISHFT(IAND(ipa, Z'0000FF00'), -8), &
ISHFT(IAND(ipa, Z'00FF0000'), -16), &
ISHFT(IAND(ipa, Z'FF000000'), -24)
nc = leftpack(string)
END FUNCTION ip_addr_to_string
[/cpp]
Here are some wrapper functions to access an ip address control in a dialog:
[cpp]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! IP Address control functions
!

SUBROUTINE IPAddressSetAddress (hwnd, controlId, addr)
IMPLICIT NONE
INTEGER, INTENT(IN) :: hwnd
INTEGER, INTENT(IN) :: controlId
TYPE(T_IN_ADDR),INTENT(INOUT) :: addr
INTEGER :: j

j = SendControlMessage (hwnd, controlId, IPM_SETADDRESS, 0, addr%s_addr)

END SUBROUTINE IPAddressSetAddress


SUBROUTINE IPAddressGetAddress (hwnd, controlId, addr)
IMPLICIT NONE
INTEGER(HANDLE), INTENT(IN) :: hwnd
INTEGER, INTENT(IN) :: controlId
TYPE(T_IN_ADDR), INTENT(INOUT) :: addr
INTEGER :: j

j = SendControlMessage (hwnd, controlId, IPM_GETADDRESS, 0, LOC(addr%s_addr))

[/cpp]



Also, on input you need to tranpose the integer format:
[cpp]!   transpose the little-endian intel format to big-endian ip format
inad%s_addr = ntohl(ip_addr%s_addr)
[/cpp]

Thanks Paul. I have the TCP protocol half working. I can send to a server, but I can't receive. I'm running a simple Python server program, which can communicate successfully back and forth with a Python client program.

The connection is established, and the Fortran client program loops on winsock_receive(). The server then sends a message, but the client doesn't get it.

ReadFile() returns 0
WSA_error() returns ERROR_IO_PENDING
WaitForSingleObject() returns WAIT_TIMEOUT

I tried the new code with WSARecv(), but that immediately gave a very large nrcv (before any message was sent from the server).

Any ideas?
0 Kudos
Paul_Curtis
Valued Contributor I
3,340 Views
Gib,
My code

  1. runs within a communications thread which is separate from the main program thread, so neither loads the other (actually I typically have many comm threads going simultaneously);
  2. is designed for query/response interchanges with devices which "speak only when spoken to", and do so promptly (ie, will not wait for you to wheel your chair over to the other computer and type something in);
  3. presumes that the socket stays open after a query has been sent, waiting for a reply to the same socket, which is then closed when the interchange completes; the default wait time is 1000ms, which can be increased if your device has a really slow response.
If the socket is open and the response arrives before you get to ReadFile, the response will be buffered by the Windows network layer (probably at least up to 8Kb), so ReadFile would have no trouble recovering the message in that case.

BTW, you first want to make sure your host can ping the ip of your target; if a basic ping times out you have a network problem. HTH
0 Kudos
gib
New Contributor II
3,340 Views
Quoting - Paul Curtis
Gib,
My code

  1. runs within a communications thread which is separate from the main program thread, so neither loads the other (actually I typically have many comm threads going simultaneously);
  2. is designed for query/response interchanges with devices which "speak only when spoken to", and do so promptly (ie, will not wait for you to wheel your chair over to the other computer and type something in);
  3. presumes that the socket stays open after a query has been sent, waiting for a reply to the same socket, which is then closed when the interchange completes; the default wait time is 1000ms, which can be increased if your device has a really slow response.
If the socket is open and the response arrives before you get to ReadFile, the response will be buffered by the Windows network layer (probably at least up to 8Kb), so ReadFile would have no trouble recovering the message in that case.

BTW, you first want to make sure your host can ping the ip of your target; if a basic ping times out you have a network problem. HTH
I'm seeing some interesting behaviour. First, I'm running server and client on the same machine (which is unloaded), using 127.0.0.1, so there is no issue of latency.

I've set up a Python server that just echoes back received messages. Immediately after a connection is made it sends a greeting message, then it loops receiving messages and sending them back. After connecting the client is in a loop, first receiving a message, then sending a string entered at the console. This works fine. But if there is a delay before the first message is sent from the server, and WaitForSingleObject() returns with WAIT_TIMEOUT, subsequent calls to winsock_receive() all fail in the same way, i.e. the greeting message is never received. It seems that possibly something needs to be reset after that first time winsock_receive() fails to get a message.

I sense that I'm very close to getting this working.

Any ideas?


I think I've cracked it. If ReadFile() times out, this pending asynchronous I/O operation must be cancelled before another attempt is made. This is done with cancelIo():

CASE (WAIT_TIMEOUT)
mode = 4
nc = cancelIo(wp%handle)

With this addition all seems to be working.

Thanks very much, Paul, you've saved me a tremendous amount of effort.

Gib
0 Kudos
Paul_Curtis
Valued Contributor I
3,340 Views
Quoting - gib
CASE (WAIT_TIMEOUT)
mode = 4
nc = cancelIo(wp%handle)

That's really interesting. Strangely, I have never had that sort of hangup, but reading the chat on CancelIO() indicates this is exactly what is needed to recover after a timeout. I looked through many examples of winsock setups in C while devising my F90 version, and somehow never saw that function imbedded in the timeout response. Thanks for your efforts.
0 Kudos
Zhanghong_T_
Novice
3,340 Views
Dear all,

Is there any complete example about using winsock in IVF?

I need to the server/client system with the client sending the calculation information and the server listen to the message and then launch some software (for example, the Ansoft Maxwell) to do the calculation, and then send results back to the client.


Thanks,
Zhanghong Tang
0 Kudos
Reply