Charles W Howard wrote:
> Is there a set of code available for FORTRAN to read TCP/IP sockets?
While this may not answer your question per se, since you asked for
FORTRAN (77?...you certainly cannot write such code in standard Fortran
if that is what you were asking for), attached are Fortran 2003 codes
that use the simple socket library libmsock
(http://www.muquit.com/muquit/software/libmsock/) and C Interop
features of Fortran 2003 in order to use sockets for interprocess/host
communication. It literally took more time to google for a simple
socket library than to write the Fortran codes.
The library libsockm is much easier for me to interface to then the full
BSD socket interface. In general it is often easier/better to do the
bulk of the work inside C and then just provide a simple interface that
does whatever the actual need of the Fortran program are, rather than
bind to the full C interface with all its complexity. Ian Bush
mentioned not long ago that he has a module to give Fortran access to
Unix shared memory segments---there also the majority of the "work" is
in C using standard unix interfaces, and the Fortran codes only provide
a top-level interface sufficient for the needs of the Fortran programs.
The attached codes are aasy to compile and run. On my system the server
program hangs at program exit, but so does the C example provided on
the libmsock webpage, so the problem is not in the Fortran program. I
don't know enough (or care enough) about sockets to fix that, but the
authors of the library can probably help:
f95 -c sockets.f90
f95 server.f90 -o server.x -L./libmsock -lmsock
f95 client.f90 -o client.x -L./libmsock -lmsock
__________
server.x # Start this first
Client connected!
Client said: Hello!
Client said: My name is Aleksandar
Client disconnected
# It hangs--the child process exits but the parent does not???
__________
client.x # Then run this
Enter what you want to tell the server:
Hello!
My name is Aleksandar
quit
__________
Best,
Aleks
MODULE MSockets
! Interface to libmsock
! A library for TCP/IP client-server applications on Unix by Muhammad A Muquit
! http://www.muquit.com/muquit/software/libmsock/libmsock.html
USE ISO_C_BINDING
IMPLICIT NONE
PUBLIC
INTEGER, PARAMETER :: C_SIZE_T=C_INT
INTERFACE
! Interfaces for the main functions
! int close(int fildes)
! This one is not in libmsock technically but is needed to close sockets:
FUNCTION CloseSocket(fildes) BIND(C,NAME="close") RESULT(error)
IMPORT
INTEGER(C_INT), VALUE :: fildes
INTEGER(C_INT) :: error
END FUNCTION
! int ServerSocket(u_short port,int max_servers);
FUNCTION ServerSocket(port,max_servers) BIND(C,NAME="ServerSocket") RESULT(sockfd)
IMPORT
INTEGER(C_SHORT), VALUE :: port
INTEGER(C_INT), VALUE :: max_servers
INTEGER(C_INT) :: sockfd
END FUNCTION
! int ClientSocket(char *netaddress,u_short port);
FUNCTION ClientSocket(netaddress,port) BIND(C,NAME="ClientSocket") RESULT(sockfd)
IMPORT
CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: netaddress
INTEGER(C_SHORT), VALUE :: port
INTEGER(C_INT) :: sockfd
END FUNCTION
! int sockGets(int sockfd,char *str,size_t count);
FUNCTION sockGets(sockfd,str,count) BIND(C,NAME="sockGets") RESULT(length)
IMPORT
INTEGER(C_INT), VALUE :: sockfd
CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: str
INTEGER(C_SIZE_T), VALUE :: count
INTEGER(C_INT) :: length ! Bytes read
END FUNCTION
! int sockRead(int sockfd,char *str,size_t count);
FUNCTION sockRead(sockfd,str,count) BIND(C,NAME="sockRead") RESULT(error)
IMPORT
INTEGER(C_INT), VALUE :: sockfd
INTEGER(C_SIZE_T), VALUE :: count
CHARACTER(C_CHAR), DIMENSION(count), INTENT(OUT) :: str
INTEGER(C_INT) :: error
END FUNCTION
! int sockPuts(int sockfd,char *str);
FUNCTION sockPuts(sockfd,str) BIND(C,NAME="sockPuts") RESULT(error)
IMPORT
INTEGER(C_INT), VALUE :: sockfd
CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: str ! NULL terminated
INTEGER(C_INT) :: error
END FUNCTION
! int sockWrite(int sockfd,char *str,size_t count);
FUNCTION sockWrite(sockfd,str,count) BIND(C,NAME="sockWrite") RESULT(error)
IMPORT
INTEGER(C_INT), VALUE :: sockfd
INTEGER(C_SIZE_T), VALUE :: count
CHARACTER(C_CHAR), DIMENSION(count), INTENT(IN) :: str
INTEGER(C_INT) :: error
END FUNCTION
END INTERFACE
END MODULE
PROGRAM MSockets_Server
USE ISO_C_BINDING
USE MSockets
IMPLICIT NONE
INTEGER(C_SHORT) :: port
INTEGER(C_INT) :: sockfd
CHARACTER(KIND=C_CHAR, LEN=1024) :: buffer
INTEGER(C_SIZE_T) :: count
INTEGER(C_INT) :: length, error
port=HUGE(port) ! Most likely unused port
sockfd=ServerSocket(port,2_c_int) ! It will return only once a connection is made
IF(sockfd<0) STOP "Failed to open server socket"
WRITE(*,*) "Client connected!"
DO
length=sockGets(sockfd,buffer,INT(LEN(buffer),C_SIZE_T))
IF(length<0) EXIT
IF(length>0) WRITE(*,*) "Client said: ", buffer(1:length)
END DO
WRITE(*,*) "Client disconnected"
error=CloseSocket(sockfd)
IF(error<0) STOP "Failed to close server socket"
END PROGRAM
PROGRAM MSockets_Server
USE ISO_C_BINDING
USE MSockets
IMPLICIT NONE
INTEGER(C_SHORT) :: port
INTEGER(C_INT) :: sockfd
CHARACTER(KIND=C_CHAR, LEN=1024) :: buffer
INTEGER(C_SIZE_T) :: count
INTEGER(C_INT) :: length, error
port=HUGE(port) ! Most likely unused port
sockfd=ClientSocket("atom.princeton.edu",port)
IF(sockfd<0) STOP "Failed to open client socket"
WRITE(*,*) "Enter what you want to tell the server:"
DO
READ(*,"(A)") buffer
IF(buffer=="quit") EXIT ! Last input
error=sockPuts(sockfd,TRIM(buffer)//C_NEW_LINE)
IF(error<0) STOP "Server died!"
END DO
error=CloseSocket(sockfd)
IF(sockfd<0) STOP "Failed to close client socket"
END PROGRAM
|