无法连接到本地计算机上的套接字

时间:2013-02-04 00:25:27

标签: sockets f#

我对example C# code here进行了简单的翻译:

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

我确保首先在我的机器上打开端口50000,用于TCP的入站和出站连接。 (我甚至尝试完全禁用防火墙。)似乎没有什么工作。我一直收到错误消息:

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

我正在使用Windows 8.我真的很感激我可能尝试的其他一些指示。

提前感谢您的时间。


修改

我希望我没有违反任何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

我在Google和Bing上广泛关注,没有任何运气。


编辑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防火墙中允许的程序列表中,打开了入站和出站连接的相关端口,完全禁用了防火墙 - 一切都无济于事。

3 个答案:

答案 0 :(得分:6)

我认为发生的事情是你连接两次,其中一个地址连接正常。然后,您的代码会一直查看剩余的地址并尝试再次连接。

您的代码缺少C#代码中的break

一些可能的解决方案:

  1. 使用while循环代替Seq.map
  2. map
  3. 中使用参考变量
  4. 将所有代码压缩到Seq.find并删除对地图的调用(可能是最优雅的)

答案 1 :(得分: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

编辑:我做了一点挖掘,并且“主动拒绝”是该错误消息的关键,根据:No connection could be made because the target machine actively refused it。简而言之,仔细检查您尝试连接的服务器是否设置正确;当连接主动被拒绝时,没有防火墙问题 - 服务器实际上拒绝了您的连接。

如果您完全确定服务器设置正确,那么您可以尝试最后一件事。根据{{​​3}},您可能需要使用Socket Connection Is Actively Refused (MSDN Forums)为IPEndPoint正确设置端口值。在这种情况下,只需将其添加为connectSocket函数中的第一行(上图):

let port = IPAddress.NetworkToHostOrder port

编辑2 :查看您发布的netstat信息 - 端口50000上没有服务器LISTENING。如果您确定服务器软件设置正确,确保它使用你想要的端口(而不仅仅是选择一个随机端口)。

答案 2 :(得分:0)

首先,我要感谢所有人,尤其是@Jack P.和@John Palmer,感谢他们阅读我的代码并提供非常好的和有益的建议。非常感谢您的指导。


我通过使用TcpListenerTcpClient类来规避上述问题。所以我想我会编写this server functionthis client function的简单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

将代码放在单独的项目中,编译并运行它们。他们在我的机器上工作。