我对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防火墙中允许的程序列表中,打开了入站和出站连接的相关端口,完全禁用了防火墙 - 一切都无济于事。
答案 0 :(得分:6)
我认为发生的事情是你连接两次,其中一个地址连接正常。然后,您的代码会一直查看剩余的地址并尝试再次连接。
您的代码缺少C#代码中的break
。
一些可能的解决方案:
Seq.map
map
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,感谢他们阅读我的代码并提供非常好的和有益的建议。非常感谢您的指导。
我通过使用TcpListener
和TcpClient
类来规避上述问题。所以我想我会编写this server function和this 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
将代码放在单独的项目中,编译并运行它们。他们在我的机器上工作。