Ubuntu 下 Fortran 网络编程入门
一 环境准备
二 方案一 调用 C 的 Socket API 入门
program tcp_echo_minimal
use, intrinsic :: iso_c_binding
implicit none
integer(c_int), parameter :: AF_INET = 2, SOCK_STREAM = 1, IPPROTO_TCP = 6
integer(c_int) :: server_fd, client_fd, n
character(len=256) :: buf
! 声明 C 函数接口
interface
function socket(domain, type, protocol) bind(C, name="socket")
import c_int; integer(c_int), value :: domain, type, protocol; integer(c_int) :: socket
end function socket
function bind(sockfd, addr, addrlen) bind(C, name="bind")
import c_int, c_ptr; integer(c_int), value :: sockfd; type(c_ptr), value :: addr, addrlen; integer(c_int) :: bind
end function bind
function listen(sockfd, backlog) bind(C, name="listen")
import c_int; integer(c_int), value :: sockfd, backlog; integer(c_int) :: listen
end function listen
function accept(sockfd, addr, addrlen) bind(C, name="accept")
import c_int, c_ptr; integer(c_int), value :: sockfd; type(c_ptr), value :: addr, addrlen; integer(c_int) :: accept
end function accept
function recv(sockfd, buf, len, flags) bind(C, name="recv")
import c_int; integer(c_int), value :: sockfd, len, flags; character(kind=c_char) :: buf(*); integer(c_int) :: recv
end function recv
function send(sockfd, buf, len, flags) bind(C, name="send")
import c_int; integer(c_int), value :: sockfd, len, flags; character(kind=c_char) :: buf(*); integer(c_int) :: send
end function send
subroutine close(fd) bind(C, name="close")
import c_int; integer(c_int), value :: fd
end subroutine close
end interface
server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if (server_fd < 0) stop 'socket failed'
! TODO: 使用 c_loc 与 C 的 sockaddr_in 正确设置地址与端口(含 htons/INADDR_ANY),然后 bind/listen/accept
! client_fd = accept(server_fd, ...)
! do
! n = recv(client_fd, buf, len(buf), 0)
! if (n <= 0) exit
! call send(client_fd, buf, n, 0)
! end do
! call close(client_fd); call close(server_fd)
end program tcp_echo_minimal
三 方案二 使用 libcurl 发起 HTTP 请求
program http_get
use, intrinsic :: iso_c_binding
implicit none
interface
function curl_easy_init() bind(C, name="curl_easy_init") result(curl)
import c_ptr; type(c_ptr) :: curl
end function curl_easy_init
function curl_easy_setopt(curl, opt, param) bind(C, name="curl_easy_setopt")
import c_ptr, c_int; type(c_ptr), value :: curl; integer(c_int), value :: opt; type(c_ptr), value :: param; integer(c_int) :: curl_easy_setopt
end function curl_easy_setopt
function curl_easy_perform(curl) bind(C, name="curl_easy_perform")
import c_ptr, c_int; type(c_ptr), value :: curl; integer(c_int) :: curl_easy_perform
end function curl_easy_perform
subroutine curl_easy_cleanup(curl) bind(C, name="curl_easy_cleanup")
import c_ptr; type(c_ptr), value :: curl
end interface
type(c_ptr) :: curl
character(len=*), parameter :: URL = "http://example.com" // c_null_char
integer(c_int) :: res
curl = curl_easy_init()
if (curl == c_null_ptr) then
print *, "curl init failed"
stop
end if
call curl_easy_setopt(curl, 10002_c_int, c_loc(URL)) ! CURLOPT_URL
call curl_easy_setopt(curl, 52_c_int, 1_c_int) ! CURLOPT_FOLLOWLOCATION
res = curl_easy_perform(curl)
if (res /= 0) then
print *, "curl_easy_perform failed: ", res
end if
call curl_easy_cleanup(curl)
end program http_get
四 常见问题与排查