Fortran Coder

查看: 16371|回复: 14
打印 上一主题 下一主题

[绘图界面库] fortran语言实现socket通信/winsock

[复制链接]

12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
跳转到指定楼层
楼主
发表于 2015-7-27 20:38:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
fortran语言实现tcpip功能,用socket选项实现实现数据交换。比如在同一台电脑中同时使用fortran语言编写的程序和c++语言编写的程序,实现两个程序之间的数据交换。c语言中有socket选项,fortran语言如何实现呢?
分享到:  微信微信
收藏收藏 点赞点赞1 点踩点踩

955

帖子

0

主题

0

精华

大师

F 币
188 元
贡献
77 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
沙发
发表于 2015-7-27 22:02:34 | 只看该作者
首先你要知道,语言本身并没有,也不会有socket通讯功能。
其实C语言本身也不规定如何使用 socket,它只规定逻辑关系和数学计算的写法。
具体到各平台下的实现,是编译器和第三方库的事情。
换过来说,socket 是一个网络通讯规范,本身也不规定如何使用。像 winsock 一类的库才是它的实现,类似的还有 Java 的 Jsocket 接口等等。注意 winsock 不等于 socket。
理解了这两个问题,才能回到你的问题上。如果你是在 windows 上 intel fortran 通过 winsock 来实现的话,那么可以 Use ws2_32 来使用 windows 标准的 ws2_32 的 API 库实现。
如果你是在其他平台(Linux),使用其他编译器,通过其他 socket 的接口(如LSocket,ServerSocket等)实现,那么用法会不一样。这一点请你深刻理解!

以下是我曾经写过的一个 UDP 协议的封装。仅供参考,具体细节请翻阅 winsock 文档!

注意它有使用局限性:
1.仅限windows,使用 winsocket接口
2.仅限Intel fortran
3.仅限 UDP 协议,TCP/IP协议请照猫画虎。

[Fortran] 纯文本查看 复制代码
01Module SocketMod
02  Use ws2_32 , ID_Cancel => IDCancel
03  Use kernel32 , only : sleep
04  Implicit None 
05  Type t_sockaddr_union
06    Sequence
07    union
08      map
09        Type (t_sockaddr_in) sockaddrin
10      end map
11      map
12        Type (t_sockaddr) sockaddr
13      end map
14    end union
15  End Type t_sockaddr_union
16  Integer , parameter , private :: winsock_v2_2 = x'202' , success = 0 !版本
17contains
18 
19  Integer Function Socket_UDP_Conn( host , port )
20    Character(len=15) host
21    Integer(kind=2) port
22    type (t_wsadata) WSAInfo !版本信息结构
23    !integer receivelen , iSendLen     , ic
24    type (t_sockaddr_union) ConnectionInfo !Client_add
25    Integer hSocket , status , i
26    Socket_UDP_Conn = 0
27    status = WSAStartup(winsock_v2_2, WSAInfo)
28    If (status/=success) return
29! 创建套接字
30    hSocket = Socket( af_inet , SOCK_DGRAM , ipproto_udp )
31    If (hSocket==invalid_socket) goto 999
32    ConnectionInfo.sockaddrin.sin_family = af_inet
33    ConnectionInfo.sockaddrin.sin_port = htons( port )
34    ConnectionInfo.sockaddrin.sin_addr%s_addr = inet_addr( host( 1 : len_trim(host) ) )
35    status = Connect(hSocket, %ref(ConnectionInfo%sockaddr), sizeof(ConnectionInfo%sockaddr))
36    If (status==socket_error) return       
37    i = 1
38    status = ioctlsocket( hSocket , FIONBIO , loc(1) )
39    Socket_UDP_Conn = hSocket
40    return
41999 status = WSACleanup()
42  End Function Socket_UDP_Conn
43   
44  Integer Function Socket_UDP_Disconn( hSocket )
45    integer :: hSocket
46    Socket_UDP_Disconn = CloseSocket( hSocket )
47    Socket_UDP_Disconn = WSACleanup()
48  End Function Socket_UDP_Disconn
49   
50  Integer Function Socket_UDP_Send( hSocket , c , len_c )
51    Character(len=*) :: c
52    Integer :: len_c   
53    Integer hSocket , iSendLen
54    Socket_UDP_Send = 0
55    iSendLen = Send( hSocket , c , len_c , 0 )
56    If ( iSendLen < 0 ) return
57    Socket_UDP_Send = 1
58  End Function Socket_UDP_Send
59   
60  Integer Function Socket_UDP_Recv( hSocket , c , len_c , timeout )
61    Character(len=*) :: c
62    Integer :: len_c , timeout  
63    Integer :: hSocket , receivelen , i
64    Socket_UDP_Recv = 0
65    c = char(0)
66    do i = 1 , timeout
67      receivelen = Recv( hSocket , c , len_c , 0 )
68      If ( receivelen == len_c ) goto 999
69      call sleep(10)
70    end do
71    return
72999 Socket_UDP_Recv = 1
73  End Function Socket_UDP_Recv
74   
75End Module SocketMod


12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
板凳
 楼主| 发表于 2015-7-27 22:41:31 | 只看该作者
vvt 发表于 2015-7-27 22:02
首先你要知道,语言本身并没有,也不会有socket通讯功能。
其实C语言本身也不规定如何使用 socket,它只规 ...

非常感谢您.
我现在刚开始接触这方面的知识,所以看到c++书中有socket这类的东西,而fortran语言书中却没有介绍,所以有这种疑惑。
我用的是win7系统,然后装了intel fortran,集成到vs上面。
这几天在查阅这方面的资料,网上这方面相关的资料很少。请问您有这方面相关的资料吗?或者说我去看一些什么样的资料?
不胜感谢!

955

帖子

0

主题

0

精华

大师

F 币
188 元
贡献
77 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
地板
发表于 2015-7-28 08:19:01 | 只看该作者
C++的书讲到 socket 也是正常的,但应该会告诉你,这是具体实现,而非 C++ 的语法。
我不清楚你看到的部分,是否是通过 winsock 接口的
正如我前面所说,winsock不等于socket,前者是后者的一个实现方式,而后者是一种通讯规范。
就好像 USB 是通讯规范,而 U 盘是具体的实现。实际上,一些鼠标,风扇,充电器也使用 USB接口


你可以学习底层的 socket 通讯协议,但是这似乎没什么卵用。因为你很难在底层上实现 socket。
大多数应用程序的程序员,都是使用 winsock 或 Jsocket 或其他实现来搞。

例如 winsock,是windows封装的socket协议接口,注意是接口。
那么,如果你打算用 winsock,你可以查看winsock相关的资料,例如 MSDN library,找 winsock 的资料时,请忘记 Fortran
等学会 winsock 以后,再来学习如何用 Fortran 来调用它。

其实 winsock 一共只有20多个函数,常用的只有七八个,如我的代码里提到的
WSAStartup
Socket
Connect
ioctlsocket
WSACleanup
Send
Recv

,还是比较简单的。(任何语言通过 winsock 接口操作,使用到的函数都是相同的,只是写法会有差异)

12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
5#
 楼主| 发表于 2015-7-28 09:18:44 | 只看该作者
vvt 发表于 2015-7-28 08:19
C++的书讲到 socket 也是正常的,但应该会告诉你,这是具体实现,而非 C++ 的语法。
我不清楚你看到的部分 ...

嗯嗯 好的,谢谢指教。我先去学习winsock。

12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
6#
 楼主| 发表于 2015-8-10 15:18:27 | 只看该作者
vvt 发表于 2015-7-28 08:19
C++的书讲到 socket 也是正常的,但应该会告诉你,这是具体实现,而非 C++ 的语法。
我不清楚你看到的部分 ...


[Fortran] 纯文本查看 复制代码
001subroutine exchangedata(iDof,iblock,dpred,rfoutput)
002      use ws2_32
003      use kernel32
004 
005      character*500 dpred
006      character*500 d
007      integer iDof,iblock
008      character*500 rfoutput
009      dimension fdpred(iblock)
010 
011 
012      type t_sockaddr_union
013          sequence
014          union
015              map
016                  type(t_sockaddr_in)sockAddrIn
017              end map
018              map
019                  type(t_sockaddr)sockAddr
020              end map
021          end union
022      end type t_sockaddr_union
023 
024      parameter(iwinsock_v2_2=x'202',isuccess=0) 
025      type(t_wsadata) WSAInfo !版本信息结构
026      type (t_sockaddr_union) ConnectionInfo !Client_add
027 
028      type T_client_server_message
029          union
030              map
031                  character*(500) buffer
032              end map
033              map
034                  character*(500) bufferout
035              end map
036          end union
037      end type
038      type(T_client_server_message) ClientServerMessage
039 
040      Character(len=15) host
041      Integer(kind=2) iport
042 
043 
044c**************************************************************************      
045 
046         ! Initialize Winsock v2
047         istatus=WSAStartup(iwinsock_v2_2,WSAInfo)
048      If (istatus.NE.isuccess)then
049         write(*,*)'WSAStartup-',istatus
050      stop
051      end if
052 
053         ! 创建套接字
054      isender = socket( af_inet , SOCK_STREAM , ipproto_tcp )
055      if (isender.EQ.invalid_socket) then
056       write(*,*)'socket-',invalid_socket
057       istatus=WSACleanup()
058      end if
059 
060        !设置连接地址
061      host='127.0.0.1'
062      iport=5001
063 
064 
065      ConnectionInfo%sockaddrin%sin_family = af_inet
066      ConnectionInfo%sockaddrin%sin_port = htons( iport )
067      ConnectionInfo%sockaddrin%sin_addr%s_addr =
068     *        inet_addr( host( 1 : len_trim(host) ) )
069      istatus = connect(isender, %ref(ConnectionInfo%sockaddr),
070     *         sizeof(ConnectionInfo%sockaddr))
071      If (istatus.EQ.socket_error) then
072      write(*,*)"连接失败"
073      end if
074c*****************************************************************************************
075      ! 接收数据
076      ireceivelen=recv(isender,ClientServerMessage%buffer,500,0)
077         if(ireceivelen<0)then
078          write(*,*)"连接失败"
079          stop
080         else
081             dpred=ClientServerMessage%buffer
082             write(*,*)"sever say:"
083             write(*,*) dpred
084             read(dpred,*) fdpred
085             write(*,*) fdpred
086         end if
087 
088c***********************************************************************************        
089 
090         ! 发送数据
091      write(*,*)"please enter message:"
092      write(*,*) rfoutput
093      ClientServerMessage%bufferout=rfoutput
094      isendlen=send(isender,ClientServerMessage%bufferout,500,0)
095      write(*,*) ClientServerMessage%bufferout
096      rfoutput=ClientServerMessage%bufferout
097      write(*,*) rfoutput
098      if(isendlen<0)then
099          write(*,*)"连接失败"
100      end if
101 
102             istatus=closesocket(isender)
103             istatus=WSACleanup()
104 
105      end subroutine

您好,这是我看着网上编的一个子程序,但是在传输数据时出现了问题。传回来的字符串类型,但是字符串后面有很多空格。然后我怎样将字符串类型转化转化为一个向量。同时一个数据向量怎样发送出去呢?

742

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
726 元
贡献
371 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

7#
发表于 2015-8-10 15:33:50 | 只看该作者
你定义的 character*(500) bufferout 就是字符串啊,所以当然就是字符串了。
fortran 直接操作字符串会在后面自动加空格。

我的习惯是用 Equivalence 方便处理:
[Fortran] 纯文本查看 复制代码
01Type T_DAQ
02    SEQUENCE
03    character(len=3) :: cFlagStart !// 一般会有帧头,但不是必须的
04    !// 此处是你的各数据,用 type 会更方便多种不同数据放在一起
05    character(len=3) :: cFlagEnd !// 一般会有帧尾,但不是必须的
06  End Type T_DAQ
07 
08type(T_DAQ) , private :: stDAQ !// 这是你真正的数据
09character(len=80) , private :: C_DAQ !// 这是为了方便书写
10Equivalence( C_DAQ , stDAQ ) !// 让 C_DAQ 和 stDAQ 公用一个内存地址!这样,当你传输时,使用 C_DAQ,而使用时,使用 stDAQ


12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
8#
 楼主| 发表于 2015-8-10 16:11:27 | 只看该作者
楚香饭 发表于 2015-8-10 15:33
你定义的 character*(500) bufferout 就是字符串啊,所以当然就是字符串了。
fortran 直接操作字符串会在后 ...

恩恩,您的这个有点高级,看不太懂。
我的Log文件里面的文本是这样的:


sever say:
0.00012393  0.00012393  0.00012393  0.00012393
@    牫=    l薰     8?   
  葕    膴    ?=     :=    `:=     薰     `?     >=    @==         
   ?       @       @?    €?    `?    @p3                              
    ?       ?6     ?    8&     ?                                   劺4
            ?6                  ?              `B+           €?    来?
      拇?     `?    却?     €B    ?     q〩            ?              ?
                     ?   


我只是需要前面的四个数,然后后面的从matlab输过来时时空格,不知为啥就乱码了。我只想提取前面的数据组成一个实型的向量,这个该怎么解决一下?

955

帖子

0

主题

0

精华

大师

F 币
188 元
贡献
77 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
9#
发表于 2015-8-11 08:24:59 | 只看该作者
我不知道你的发送方是什么,代码是怎么样的。
从表现来看,后面的不是文本内容,是二进制内容。

12

帖子

2

主题

0

精华

入门

F 币
78 元
贡献
29 点
10#
 楼主| 发表于 2015-8-11 09:03:18 | 只看该作者
vvt 发表于 2015-8-11 08:24
我不知道你的发送方是什么,代码是怎么样的。
从表现来看,后面的不是文本内容,是二进制内容。 ...

发送方是matlab,代码如下:
fwrite(Tcpsever,num2str(dpredout'));
其中dpredout是一个1*4向量,转化为字符串发送。
按理来说后面的应该是空格才对,却不知为何乱码了。然后我想读取空格前面的那些数据,然后存到一个向量里面。这该怎么做?
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2025-4-29 19:13

Powered by Discuz! X3.4

© 2013-2025 Comsenz Inc.

快速回复 返回顶部 返回列表