はじめに
Task and gen_tcpを読みながらやっても、TCPサーバーがうまく反応してくれなかったのですが、一応反応してくれたので残しておきます。
TCPサーバー
defmodule Tcp1 do
@moduledoc """
Tcp1 keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""
require Logger
def accept(port) do
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true])
Logger.info("Accepting connections on port #{port}")
loop_acceptor(socket)
end
defp loop_acceptor(socket) do
{:ok, client} = :gen_tcp.accept(socket)
Logger.info("Connected")
serve(client)
loop_acceptor(socket)
end
defp serve(socket) do
socket
|> read()
|> write(socket)
serve(socket)
end
defp read(socket) do
{:ok, data} = :gen_tcp.recv(socket, 0)
Logger.info(data)
data
end
defp write(line, socket) do
:ok = :gen_tcp.send(socket, line)
end
end
この行に変更を加えてあります。↓
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true])
もともとはpacket: :line
と書いてあったのですが、そのままだと動きませんでした。
クライアントから送られてくるデータが1行ずつ送信されてくるとかではなく、生のデータとして送信されているからのようです。
なので、packet: 0
もしくはpacket: :raw
というふうに変更したら動きました。
※Line-Basedなプロトコル(\rとか\nで区切られてるようなやつ)を扱うときはちゃんと:line
と指定してあげないとだめなようです。
TCPクライアント
defmodule Tcp2 do
@moduledoc """
Tcp2 keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""
require Logger
@msg "msg from me"
def connect() do
{:ok, socket} = :gen_tcp.connect('localhost', 4040, [:binary, active: false])
send_messages(socket)
end
defp send_messages(socket) do
:timer.sleep(1000)
:ok = :gen_tcp.send(socket, @msg)
Logger.info(@msg)
{:ok, _data} = :gen_tcp.recv(socket, 0)
send_messages(socket)
end
end
1秒経つごとに、"msg from me"というデータを接続先のサーバーに送信してくれます。
さいごに
とりあえず試しに動くようなものができました。
:line
とか:raw
とかそのへんはまた実装していく上で調べながら注意していこうと思います。
参考リンク
https://elixirforum.com/t/i-can-connect-using-gen-tcp-but-i-cant-send-receive-data-what-is-wrong-with-this-implementation/6487/4
https://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/design/line_based.html