使用c#program

时间:2015-12-16 17:16:06

标签: c# erlang server binaries

我试图为我的程序编写Erlang服务器,但仍然遇到一些我无法处理的问题。使用它时(我在erlang中编写了客户端来测试服务器):

send(Socket, Message) ->
BinMsg = term_to_binary(Message),
gen_tcp:send(Socket, Message).
一切似乎都没问题,但是当我试图从我的c#客户端发送内容时,服务器会看到连接和断开连接,但看不到消息(它甚至没有反应)

theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
String foo = theLine + "\r\n"; 
test = System.Text.Encoding.UTF8.GetBytes(foo);
theWriter.Write(test);

我意识到这可能是Erlang的一些问题

  

term_to_binary()

但我不知道如何解决它。我需要简单:

  1. 客户端将数据转换为字节
  2. 客户端将数据发送到服务器
  3. 服务器对数据进行编码
  4. 服务器决定做什么
  5. 服务器生成新数据,将其转换为字节并发送到客户端
  6. 客户端对其进行编码
  7. 我可以在字符串上做到这一点,但我不认为这种方法会很好,我想发送二进制文件而不是字符串。任何建议?

2 个答案:

答案 0 :(得分:1)

您应该在客户端正确编码数据,以便能够在Erlang中使用term_to_binary/binary_to_term。看一下http://erlang.org/doc/apps/erts/erl_ext_dist.html它并不难实现,我认为应该有现有的解决方案。

但是从你的话来看,你的代码看起来有些不对劲,因为Erlang应该在错误的二进制文件上抛出异常。可能与{active, true|false|once|N}有关。您应该在socket上设置{active, true}以便能够接收TCP数据包,因为Erlang消息(onceN也很好,请查看docs:http://erlang.org/doc/man/gen_tcp.html)。如果你想接收二进制文件,你应该在socket上设置binary选项。

答案 1 :(得分:0)

所以这是我的服务器/客户端代码:

-define(TCP_OPTIONS, [binary, {packet, 2}, {active, false}, {reuseaddr, true}]).
-define(PORT, 8080).

-spec start(Port) -> pid() when
  Port::integer().
start(Port) ->
  process_flag(trap_exit, true),
  ClientDict = dict:new(),
  GamesDict = dict:new(),
  HandlerPID = spawn_link(fun() -> handler(ClientDict, GamesDict) end),
  imup_listener:listen(Port, HandlerPID).





%%------------------------------
% Internal Functions
%%------------------------------

handler(Clients, Games) ->
  receive
    {insert_client, Socket, Alias} ->
      TmpClients = dict:store(Socket, Alias, Clients),
      TmpClients2 = dict:store(Alias, Socket, TmpClients),
      handler(TmpClients2, Games);
    {get_client_id, ReceiverPID, ClientPID} ->
      {ok , CID} = dict:find(ClientPID, Clients),
      ReceiverPID ! {id, CID},
      handler(Clients, Games);
    {get_client_pid, ReceiverPID, ClientID} ->
      {ok, CPID} = dict:find(ClientID, Clients),
      ReceiverPID ! {pid, CPID},
      handler(Clients, Games);
    {host_game, HostID, GameID} ->
      TmpGames = dict:append_list(GameID, [HostID], Games),
      handler(Clients, TmpGames);
    {add_player, PlayerID, GameID} ->
      TmpGames = dict:append_list(GameID, [PlayerID], Games),
      handler(Clients, TmpGames);
    {get_host, ReceiverPID, GameID} ->
      {ok, [HID|T]} = dict:find(GameID, Games),
      {ok, HPID} = dict:find(HID, Clients),
      ReceiverPID ! {host_is, HID, HPID},
      handler(Clients, Games);

    _ ->
      {error, "I don't know what you want from me :("}
  end.

监听器:

-define(TCP_OPTIONS, [binary, {packet, 2}, {active, false}, {reuseaddr, true}]).

listen(Port, HandlerPID) ->
  {ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
  spawn_link(fun() -> accept(LSocket, HandlerPID) end),
  LSocket.




% Wait for incoming connections and spawn a process that will process incoming packets.
accept(LSocket, HandlerPID) ->
  {ok, Socket} = gen_tcp:accept(LSocket),
  Pid = spawn(fun() ->
    io:format("Connection accepted ~n", []),
    %%DictPID ! {insert, Socket, Socket},
    loop(Socket, HandlerPID)
              end),
  gen_tcp:controlling_process(Socket, Pid),
  accept(LSocket, HandlerPID).



% Echo back whatever data we receive on Socket
loop(Sock, HandlerPID) ->

  inet:setopts(Sock, [{active, once}]),
  receive
    {tcp, Socket, Data} ->
      io:format("wchodze pakiet"),
      io:format("Got packet: ~p == ", [Data]),

      FormatedData = process_data(Socket, Data, HandlerPID),
      io:format("~p~n", [FormatedData]),
      convey_message(Socket, FormatedData),

      loop(Socket, HandlerPID);
    {tcp_closed, Socket} ->
      io:format("wchodze closed"),
      io:format("Socket ~p closed~n", [Socket]);
    {tcp_error, Socket, Reason} ->
      io:format("wchodze error"),
      io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])
  end.




%%------------------------------
% Internal Functions
%%------------------------------


-spec process_data(S, D, P) -> term() when
  S::port(),
  D::binary(),
  P::pid().
process_data(Socket, Data, HandlerPID) when is_binary(Data) ->
  case binary_to_term(Data) of
    {send_host, GameID, Msg} ->
      HandlerPID ! {get_host, self(), GameID},
      receive
        {host_is, _HID, HSOCK} ->
          HSOCK;
        _ ->
          {error, nohost}
      end,
      Msg;
    {send_all, GameID, Msg} ->
      Msg;
    {send_to_id, ReceiverID, Msg} ->
      HandlerPID ! {get_client_pid, self(), ReceiverID},
      receive
        {pid, SockPID} ->
          gen_tcp:send(SockPID, term_to_binary(Msg));
        _ ->
          {error, noid}
      end,
      term_to_binary({ok, delivered});
    {host_game, GameID} ->
      GameID;
    {join_game, GameID} ->
      GameID;
    {start_game, GameID} ->
      GameID;
    {enter, SenderID} ->
      HandlerPID ! {insert_client, Socket, SenderID};
    Dat ->
      Dat
  end;
process_data(Socket, Data, DictPID) ->
  Data.


convey_message(Socket, Data) when is_binary(Data) ->
  gen_tcp:send(Socket, Data);
convey_message(Socket, Data) ->
  gen_tcp:send(Socket, term_to_binary(Data)).

Erlang CLient(正在工作):

connect(PortNo) ->
  {ok, Socket} = gen_tcp:connect("localhost", PortNo, [binary, {active, false}, {packet, 2}]),
  spawn(fun() -> recv(Socket) end),
  Socket.

connect(IP, PortNo) ->
  {ok, Socket} = gen_tcp:connect(IP, PortNo, [binary, {active, false}, {packet, 2}]),
  spawn(fun() -> recv(Socket) end),
  Socket.


send(Socket, Message) ->
  BinMsg = unicode:characters_to_binary(Message),
  io:format(Message ++ "~n"),
  io:format(BinMsg),
  gen_tcp:send(Socket, BinMsg).


recv(Socket) ->
  {ok, A} = gen_tcp:recv(Socket, 0),
  io:format("Received: ~p~n", [A]),
  recv(Socket).


disconnect(Socket) ->
  gen_tcp:close(Socket).

C#客户端:

using UnityEngine;
using System;
using System.IO;
using System.Net.Sockets;

//using System.Globalization.NumberStyles;



public class NetworkController : MonoBehaviour

{

    public string tekst;

    public Transform nek;

    public byte[] bytesW = new byte[4];
    public byte[] test;

    public float[] qq = new float[4];

    internal Boolean socketReady = false;

    TcpClient mySocket;

    NetworkStream theStream;

    StreamWriter theWriter;

    BStreamReader theReader;

    String Host = "localhost";

    public Int32 Port;



    void Update()

    {

        string receivedText = readSocket();

        if (receivedText != "")

        {
            tekst = receivedText;
        }

    }



    void OnGUI()

    {
        if (!socketReady)

        {
            if (GUILayout.Button("Connect"))
            {
                setupSocket();
                writeSocket("serverStatus:");
            }
        }
         if (GUILayout.Button("Send"))
         {
             writeSocket("ala");
         }
         if (GUILayout.Button("Close"))
         {
             closeSocket();
         }

        GUI.Label(new Rect(0, 40, 1000, 400), tekst);
        if (socketReady)
        {


        }
    }

    void OnApplicationQuit()

    {

        closeSocket();

    }



    public void setupSocket()

    {

        try

        {


            mySocket = new TcpClient(Host, Port);

            theStream = mySocket.GetStream();

            theWriter = new StreamWriter(theStream);

            theReader = new StreamReader(theStream);

            socketReady = true;

        }



        catch (Exception e)

        {

            Debug.Log("Socket error: " + e);

        }

    }



    public void writeSocket(string theLine)

    {

        if (!socketReady)

            return;

        //byte[] foo = System.Text.Encoding.UTF8.GetBytes(theLine);
        String foo = theLine + "\r\n"; 
        Debug.Log(foo);
        test = System.Text.Encoding.UTF8.GetBytes(foo);



        theWriter.Write(test);
        theWriter.Flush();

    }
/*
    public void WriteToStream(string theLine)
    {
        byte[] len_bytes = BitConverter.GetBytes(length);

        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(len_bytes);
        }
        writer.Write(len_bytes);

        writer.Write(content);
    }
    */



    public String readSocket()

    {

        if (!socketReady)

            return "";

        if (theStream.DataAvailable)

            return theReader.ReadLine();

        //return theReader.ReadToEnd();

        return "";

    }



    public void closeSocket()

    {

        if (!socketReady)

            return;

        theWriter.Close();

        theReader.Close();

        mySocket.Close();

        socketReady = false;

    }
}

它还没有准备好,但它应该发送基本信息,但事实并非如此。正如我所说,我对Erlang很新,所以也许我做了一些愚蠢的事情