我正在努力创建一种让多个Fortran进程相互通信的方法。这将用于模拟,其中一台机器正在运行模拟过程,而另一台机器(或可能是机器集群)将为模拟过程生成合成数据。
即:模拟过程(sp)向生成过程(gp)请求一条信息。 gp要么找到所请求的信息,要么创建它并将其返回到sp。
这两个过程都非常密集,这就是为什么它们将在多台机器之间分配的原因。
无论如何,在做了一些研究后,我能为这个IPC提出的最好的方法是使用TCP和IP。在做了一些研究之后,我能够提出以下代码(取自here):
模块
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 :: CC_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(CC_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(CC_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(CC_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(CC_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),CC_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_Client
USE ISO_C_BINDING
USE MSockets
IMPLICIT NONE
INTEGER(C_SHORT) :: port
INTEGER(C_INT) :: sockfd
CHARACTER(KIND=C_CHAR, LEN=1024) :: buffer
INTEGER(CC_SIZE_T) :: count
INTEGER(C_INT) :: length, error
port=HUGE(port) ! Most likely unused port
sockfd=ClientSocket("localhost",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
这些程序依赖于从here获取的c库以进行TCP / IP通信。一切都很好,我可以成功启动服务器;但是,当我尝试启动客户端时,我收到以下错误:
ClientSocket(): Invalid network address
STOP Failed to open client socket
我知道这个问题来自&#34; localhost&#34;在:
sockfd=ClientSocket("localhost",port)
但我不能为我的生活找出原因。我也尝试使用计算机的内部IP地址并使用公共IP地址并尝试使用多台计算机(在一台对等网络上运行时在一台机器上运行服务器,在另一台机器上运行客户机)并始终得到相同的错误。有没有人知道最新情况(或者如果你认为我的fortran IPC有更好的解决方案也给我这个)?
谢谢! 安德鲁
另外,对于它的价值,我使用gfortran在Mac OSX 10.9上运行它。我用来编译的命令是:
gfortran -c sockets.f90
gfortran client.f90 -o client.x -L"../../../libmsock/libmsock/" -lmsock -g
gfortran server.f90 -o server.x -L"../../../libmsock/libmsock/" -lmsock -g
其中名称应该清楚地表明哪个代码与哪个代码相关。
答案 0 :(得分:2)
问题是C和Fortran中字符串的不同处理。
您将"localhost"
作为Fortran字符串传递,其结尾由固定(在本例中为隐含)长度决定。在C中,字符串必须以NUL结尾。这可以通过编写
sockfd=ClientSocket("localhost"//C_NULL_CHAR, port)
其中C_NULL_CHAR
在ISO_C_BINDING
模块中定义。