2

ここでサンプルC#コードの簡単な翻訳を行いました:

let socket_CreateBindListen (sv_ : string) (pt_ : int) : Socket option =
    let (he : IPHostEntry) = Dns.GetHostEntry(sv_)
    let rsock, ipe =
        he.AddressList
        |> Seq.map (fun s ->
            let (ipe2 : IPEndPoint) = new IPEndPoint (s, pt_)
            let (rsock2 : Socket) = new Socket (ipe2.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
            rsock2.Connect ipe2 ///// <---- No connection could be made because the target machine actively refused it
            rsock2, ipe2)
        |> Seq.find (fun (s, t) -> s.Connected)
    try
        rsock.Bind ipe
        rsock.Listen 10
        printfn "%s now listening on port %d" sv_ pt_
        Some (rsock)
    with
        | _ ->
            printfn "Failed to connect to %s on port %d" sv_ pt_
            None

socket_CreateBindListen "127.0.0.1" 50000

インバウンド接続とアウトバウンド接続の両方で、TCP用にマシンのポート50000を最初に開くようにしました。(ファイアウォールを完全に無効にしてみました。)何も機能していないようです。エラーメッセージが表示され続けます:

No connection could be made because the target machine actively refused it.

私はWindows8を使用しています。他に何を試すかについて、いくつかの指針をいただければ幸いです。

よろしくお願いします。


編集

ここで私の進捗状況についてブログを書くことで、StackOverflowの投稿ポリシーに違反していないことを願っています。

コードを次のように更新しました。

let socket_CreateBindListen (sv_ : string) (pt_ : int) : Socket option =
    let (he : IPHostEntry) = Dns.GetHostEntry(sv_)
    let rsock, ipe =
        he.AddressList
        |> Seq.map (fun s ->
            let (ipe2 : IPEndPoint) = new IPEndPoint (s, pt_)
            let (rsock2 : Socket) = new Socket (ipe2.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
            try
                rsock2.Connect ipe2
                rsock2, ipe2
            with
                | _ ->
                    null, null)
        |> Seq.find (fun (s, t) -> (s <> null) && (s.Connected))
    try
        rsock.Bind ipe
        rsock.Listen sbl
        printfn "%s now listening on port %d" sv_ pt_
        Some (rsock)
    with
        | _ ->
            printfn "Failed to connect to %s on port %d" sv_ pt_
            None

今、私は次のエラーを受け取っています:

KeyNotFoundException was unhandled
An unhandled exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in FSharp.Core.dll

私はグーグルとビングを広範囲に調べましたが、運がありませんでした。


編集2

によって要求されたようにJack P.、ここに、からの出力とnetstat -a、バイナリが実行されたときに何が起こるかを示します。

PS C:\Users\shredderroy> netstat -a

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    0.0.0.0:80             SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:135            SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:445            SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:2179           SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:49152          SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:49153          SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:49154          SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:49155          SPEEDMACHINE:0         LISTENING
  TCP    0.0.0.0:49156          SPEEDMACHINE:0         LISTENING
  TCP    192.168.0.139:139      SPEEDMACHINE:0         LISTENING
  TCP    192.168.0.139:49159    bn1wns2011708:https    ESTABLISHED
  TCP    192.168.0.139:49167    vc-in-f108:imaps       ESTABLISHED
  TCP    192.168.0.139:49171    vc-in-f108:imaps       ESTABLISHED
  TCP    192.168.0.139:49239    a23-67-250-112:http    CLOSE_WAIT
  TCP    [::]:80                SPEEDMACHINE:0         LISTENING
  TCP    [::]:135               SPEEDMACHINE:0         LISTENING
  TCP    [::]:445               SPEEDMACHINE:0         LISTENING
  TCP    [::]:2179              SPEEDMACHINE:0         LISTENING
  TCP    [::]:49152             SPEEDMACHINE:0         LISTENING
  TCP    [::]:49153             SPEEDMACHINE:0         LISTENING
  TCP    [::]:49154             SPEEDMACHINE:0         LISTENING
  TCP    [::]:49155             SPEEDMACHINE:0         LISTENING
  TCP    [::]:49156             SPEEDMACHINE:0         LISTENING
  UDP    0.0.0.0:500            *:*
  UDP    0.0.0.0:4500           *:*
  UDP    0.0.0.0:5355           *:*
  UDP    127.0.0.1:53194        *:*
  UDP    127.0.0.1:60316        *:*
  UDP    127.0.0.1:61644        *:*
  UDP    192.168.0.139:137      *:*
  UDP    192.168.0.139:138      *:*
  UDP    [::]:500               *:*
  UDP    [::]:4500              *:*
  UDP    [::]:5355              *:*
  UDP    [fe80::b193:4f6:d053:6324%20]:546  *:*
PS C:\Users\shredderroy> cd "C:\Users\shredderroy\Documents\Visual Studio 2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\bin\Debug
"
PS C:\Users\shredderroy\Documents\Visual Studio 2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\bin\Debug> .\SocketTests_Server.exe
Unhandled Exception: System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it [::1]:50000
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at SocketTests_Server.TestModule_1.heo@22.Invoke(IPAddress s) in C:\Users\shredderroy\Documents\Visual Studio 2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\TestModule_1.fs:line 25 at Microsoft.FSharp.Collections.SeqModule.TryFind[T](FSharpFunc`2 predicate, IEnumerable`1 source)
   at SocketTests_Server.TestModule_1.socket_CreateBindListen_1(String sv_, Int32 pt_) in C:\Users\shredderroy\Documents\Visual Studio
2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\TestModule_1.fs:line 20
   at SocketTests_Server.Program.Main(String[] args) in C:\Users\shredderroy\Documents\Visual Studio 2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\Program.fs:line 9
PS C:\Users\shredderroy\Documents\Visual Studio 2012\Projects\FSharp\SocketTests_Server\SocketTests_Server\bin\Debug>

これからも頑張っていきます。これまでのところSocketTests_Server.exe、Windowsファイアウォールで許可されているプログラムのリストにプログラムを追加し、インバウンド接続とアウトバウンド接続に関連するポートを開き、ファイアウォールを完全に無効にしました。

4

3 に答える 3

6

何が起こっているのかというと、2回接続していて、アドレスの1つが正常に接続されていると思います。その後、コードは残りのアドレスを調べ続け、再接続を試みます。

breakあなたのコードには、C#コードに相当するものがありません。

いくつかの可能な解決策:

  1. 代わりにwhileループを使用するSeq.map
  2. 内部で参照変数を使用するmap
  3. すべてのコードを圧縮して、Seq.findマップへの呼び出しを削除します(おそらく最もエレガントです)
于 2013-02-04T00:48:53.557 に答える
5

あなたがリンクしたページからコードを翻訳しました - コンパイルはできますが、実行は試していません。

open System
open System.Text
open System.Net
open System.Net.Sockets

let connectSocket (server : string, port : int) : Socket option =
    // Get host related information.
    let hostEntry = Dns.GetHostEntry server

    // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid 
    // an exception that occurs when the host IP Address is not compatible with the address family 
    // (typical in the IPv6 case). 
    hostEntry.AddressList
    |> Seq.tryPick (fun address ->
        let ipe2 = IPEndPoint (address, port)
        let rsock2 = new Socket (ipe2.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
        rsock2.Connect ipe2
        if rsock2.Connected then
            Some rsock2
        else None)

// This method requests the home page content for the specified server. 
let socketSendReceive (server : string, port : int) : string =
    let request =
        sprintf "GET / HTTP/1.1\r\nHost: %s\r\nConnection: Close\r\n\r\n" server
    let bytesSent =
        Encoding.ASCII.GetBytes request
    let bytesReceived = Array.zeroCreate 256

    // Create a socket connection with the specified server and port.
    match connectSocket (server, port) with
    | None ->
        "Connection failed"
    | Some s ->
        // Send request to the server.
        s.Send (bytesSent, Array.length bytesSent, SocketFlags.None)
        |> ignore

        // Receive the server home page content. 
        let mutable bytes = 0
        let mutable page =
            sprintf "Default HTML page on %s:\r\n" server

        // The following will block until the page is transmitted. 
        while bytes > 0 do
            bytes <- s.Receive (bytesReceived, Array.length bytesReceived, SocketFlags.None)
            page <- page + Encoding.ASCII.GetString (bytesReceived, 0, bytes)

        page

//
let main args =
    let port = 80

    let host =
        if Array.isEmpty args then
            // If no server name is passed as argument to this program,  
            // use the current host name as the default.
            Dns.GetHostName ()
        else
            args.[0]

    socketSendReceive (host, port)
    |> Console.WriteLine

編集:少し掘り下げましたが、「積極的に拒否されました」がそのエラーメッセージの鍵です:ターゲットマシンが積極的に拒否したため、接続できませんでした。つまり、接続しようとしているサーバーが適切に設定されていることを再確認してください。接続が積極的に拒否されている場合、ファイアウォールの問題はありません。サーバーは実際に接続を拒否しています。

サーバーが正しく設定されていることを完全に確信している場合は、最後に 1 つ試すことができます。Socket Connection Is Actively Refused (MSDN Forums)によると、 IPAddress.NetworkToHostOrder メソッドを使用して、IPEndPoint のポート値を正しく設定する必要がある場合があります。その場合、これを関数の最初の行として追加するだけconnectSocketです(上記):

let port = IPAddress.NetworkToHostOrder port

編集 2 :netstat投稿した情報を見ると、LISTENINGポート 50000 にサーバーがありません。サーバー ソフトウェアが正しくセットアップされていることが確実な場合は、必要なポートを使用していることを確認してください (ランダムなポートを選択するだけではありません)。

于 2013-02-04T01:27:35.297 に答える
0

まず、私のコードを読んで、非常に有益で有益な提案を提供してくれたすべての人、特に @Jack P. と @John Palmer に感謝します。ご指導のほどよろしくお願いいたします。


TcpListener代わりにandTcpClientクラスを使用することで、上記の問題を回避しました。そこで、サーバーとクライアントを一緒に実装する、このサーバー関数このクライアント関数の単純な F# 変換を作成しようと考えました。願わくば、このサンプル コードが他の初心者の時間を節約してくれることを願っています。


サーバ

let connectAndListen () : unit =
    let (laddr : IPAddress) = IPAddress.Parse ("127.0.0.1")
    let lpt = 32000
    let (svr : TcpListener) = new TcpListener (laddr, lpt)
    try
        svr.Start ()
        let (bta : byte[]) = Array.create 256 (byte (0))
        while true do
            printfn "Waiting for a connection..."
            let (cl : TcpClient) = svr.AcceptTcpClient ()
            printfn "Connected"
            let (ns : NetworkStream) = cl.GetStream ()
            let mutable (i : int) = ns.Read (bta, 0, (Array.length bta))
            while i <> 0 do
                let (dat : string) = System.Text.Encoding.ASCII.GetString (bta, 0, i)
                printfn "Received:  %s" dat
                let (msg : byte[]) = System.Text.Encoding.ASCII.GetBytes (dat.ToUpper ())
                ns.Write (msg, 0, (Array.length msg))
                printfn "Sent:  %s" (dat.ToUpper ())
                i <- ns.Read (bta, 0, (Array.length bta))
            cl.Close ()
    with
    | excp ->
        printfn "%s" excp.Message
    svr.Stop ()

クライアント

let connect (sv_ : string) (pt_ : int) (msg_ : string) : unit =
    try
        let cl = new TcpClient (sv_, pt_)
        let (dat : byte[]) = System.Text.Encoding.ASCII.GetBytes msg_
        let (st : NetworkStream) = cl.GetStream ()
        st.Write (dat, 0, (Array.length dat))
        printfn "Sent:  %s" msg_
        let (rdat : byte[]) = Array.create 256 (byte (0))
        let (i : int) = st.Read (rdat, 0, (Array.length rdat))
        let (rsp : string) = System.Text.Encoding.ASCII.GetString (rdat, 0, i)
        printfn "Received:  %s" rsp
        st.Close ()
        st.Dispose ()
    with
    | :? ArgumentNullException as excp ->
        printfn "ArgumentNullException encountered:  %s" excp.Message
    | :? SocketException as excp ->
        printfn "SocketException encountered:  %s" excp.Message
    printfn "Press ENTER to continue"
    Console.ReadLine () |> ignore

コードを別のプロジェクトに配置し、コンパイルして実行します。彼らは私のマシンで動作します。

于 2013-02-07T01:08:28.807 に答える