当前位置:K88软件开发文章中心编程语言非主流编程语言Julia → 文章内容

Julia 网络和流

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 16:28:20

由 陈 创建, 最后一次修改 2016-08-12 网络和流Julia 提供了一个丰富的接口处理终端、管道、tcp套接字等等I/O流对象。 接口在系统层的实现是异步的,开发者以同步的方式调用该接口、一般无需关注底层异步实现。接口实现主要基于Julia支持的协程(coroutine)功能。基本流 I/O所有 Julia 流都至少提供一个 read 和一个 write 方法,且第一个参数都是流对象,例如: julia> write(STDOUT,"Hello World") Hello World julia> read(STDIN,Char) '\n'注意我又输入了一次回车,这样 Julia 会读入换行符。现在,由例子可见,write 方法的第二个参数是将要写入的数据,read 方法的第二个参数是即将读入的数据类型。例如,要读入一个简单的字节数组,我们可以: julia> x = zeros(Uint8,4) 4-element Uint8 Array: 0x00 0x00 0x00 0x00 julia> read(STDIN,x) abcd 4-element Uint8 Array: 0x61 0x62 0x63 0x64不过像上面这么写有点麻烦,还提供了一些简化的方法。例如,我们可以将上例重写成: julia> readbytes(STDIN,4) abcd 4-element Uint8 Array: 0x61 0x62 0x63 0x64 或者直接读入整行数据: julia> readline(STDIN) abcd "abcd\n"注意这取决于你的终端配置,你的 TTY 可能是行缓冲、需要多输入一个回车才会把数据传给 julia。如果你想要通过 STDIN 去读每一行,你可以使用 eachline 方法: for line in eachline(STDIN) print("Found $line") end或者如果你想要以字符为单位去读,则如下: while !eof(STDIN) x = read(STDIN, Char) println("Found: $x") end文本 I/O注意上面提到的写方法是对二进制流进行操作的。特别是,值不会被转换成任何规范的文本表示,而是会被写成如下: julia> write(STDOUT,0x61) a对于文本 I/O,可以使用 print 或 show 方法,这取决你的需求(可以查看标准库中对于两者不同之处的细节描述): julia> print(STDOUT,0x61) 97使用文件像其他的环境一样,Julia 有一个开放的函数,它以一个文件名作为参数并且返回一个 IO 流对象,通过这个 IO 流,你可以从文件中读或者写其中的内容。举个例子来说,如果我们有一个文件,hello.txt,它的内容为 “Hello, World!”: julia> f = open("hello.txt") IOStream(<file hello.txt>) julia> readlines(f) 1-element Array{Union(ASCIIString,UTF8String),1}: "Hello, World!\n"如果你想要写入某些内容到文件当中,你可以用写标志 (“w”) 打开它: julia> f = open("hello.txt","w") IOStream(<file hello.txt>) julia> write(f,"Hello again.") 12如果你用这种方式检查 hello.txt 的内容,你将会注意到它是空的;其实没有任何东西被写入磁盘。这是因为 IO 流在数据真正写到磁盘之前必须被关掉: julia> close(f)再次检查 hello.txt 将会显示它的内容已经被改变了。打开一个文件,对它的内容做一些改变,然后关闭它是一个常见的模式。为了让这个过程更简单,这里存在另一个 open 的调用,用一个方法作为其第一个参数,用文件名作为他的第二个参数,打开文件,调用该文件的方法作为一个参数,然后再次关闭它。举一个例子,给出一个方法: function read_and_capitalize(f::IOStream) return uppercase(readall(f)) end你可以调用: julia> open(read_and_capitalize, "hello.txt") "HELLO AGAIN."为了打开 hello.txt,调用它的 read_and_capitalize 方法,关闭 hello.txt 然后返回大写的内容。为了避免去定义一个已经命名的函数,你可以使用 do 语法,动态的去创建一个匿名函数: julia> open("hello.txt") do f uppercase(readall(f)) end "HELLO AGAIN."简单的 TCP 例子让我们直接用一个简单的 Tcp Sockets 的示例来说明。我们首先需要创建一个简单地服务器: julia> @async begin server = listen(2000) while true sock = accept(server) println("Hello World\n") end end Task julia>那些熟悉 Unix socket API 的人,会觉得方法名和 Unix socket 很相似,尽管他们的用法比原生 Unix socket API 要简单。第一次调用 listen 将会创建一个服务器来等待即将到来的连接,在这个案例中监听的端口为 2000。相同的方法可能会用来去创建不同的其他种类的服务器: julia> listen(2000) # Listens on localhost:2000 (IPv4) TcpServer(active) julia> listen(ip"127.0.0.1",2000) # Equivalent to the first TcpServer(active) julia> listen(ip"::1",2000) # Listens on localhost:2000 (IPv6) TcpServer(active) julia> listen(IPv4(0),2001) # Listens on port 2001 on all IPv4 interfaces TcpServer(active) julia> listen(IPv6(0),2001) # Listens on port 2001 on all IPv6 interfaces TcpServer(active) julia> listen("testsocket") # Listens on a domain socket/named pipe PipeServer(active)注意最后一次调用的返回值类型是不同的。这是因为这个服务器没有监听 TCP,而是在一个命名管道(Windows 术语)- 同样也称为域套接字(UNIX 的术语)。他们的不同之处非常微小,并且与他们的接收和连接方法有关系。接受方法会检索一个到客户端的连接,连接到我们刚刚创建的服务器端,而连接到服务器的函数使用的是特定的方法。连接方法和监听方法的参数是一样的,所以使用的环境(比如主机,cwd 等等)能够传递和监听方法相同的参数来建立一个连接。所以让我们来尝试一下(前提是已经创建好上面的服务器): julia> connect(2000) TcpSocket(open, 0 bytes waiting) julia> Hello World正如我们预期的那样,我们会看到 “Hello World” 被打印出来了。所以我让我们分析一下在后台发生了什么。当我们调用连接函数时,我们连接到了我们刚刚创建的服务器。同时,接收方法返回一个服务器端的连接到最新创建的套接字上,然后打印 “Hello World” 来表明连接

[1] [2]  下一页


Julia 网络和流