Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 使用线程时出现套接字问题_.net_Sockets_Multithreading_Socketexception - Fatal编程技术网

.net 使用线程时出现套接字问题

.net 使用线程时出现套接字问题,.net,sockets,multithreading,socketexception,.net,Sockets,Multithreading,Socketexception,有人能解释一下为什么下面的代码不起作用吗 using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; namespace SocketThreadingTest { class Program { static void Main(string[] arg

有人能解释一下为什么下面的代码不起作用吗

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace SocketThreadingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(delegate()
            {
                BeginConnect(new IPEndPoint("some address"));
            });
            t.Start();

            Console.ReadKey();
        }

        public static void BeginConnect(IPEndPoint address)
        {
            try
            {
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.BeginConnect(address, ConnectCallback, socket);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        private static void ConnectCallback(IAsyncResult ar)
        {
            Socket sock = (Socket)ar.AsyncState;
            try
            {
                sock.EndConnect(ar);
                Console.WriteLine("Connected {0}", sock.LocalEndPoint);

                sock.Send(Encoding.UTF8.GetBytes("Hello"));

                Console.WriteLine("success");
                sock.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("send ex " + ex);

                if (sock != null)
                    sock.Close();
            }
        }
    }
}
输出为(注意插座的本地端点):

当然,当我不使用线程并直接调用BeginConnect时,它可以正常工作。更令人费解的是,添加一个线程。睡眠时间足够长(1秒)也可以正常工作。 有什么想法吗?
谢谢。

您的IPEndPoint应该包含一个端口——我甚至不确定端点将如何编译,因为这是必需的。您可以将端口作为IPendeddress的第二个参数提供,或修改BeginConnect方法,如下所示:

 socket.BeginConnect(address, [port], ConnectCallback, socket); 

…其中,[port]表示服务器上的侦听端口。

使用单独的线程和BeginConnect有什么意义? 如果创建单独的线程(最好使用线程池),为什么要使用异步连接(在这种情况下,将从线程池中获取单独的线程)

有几种选择: 使用线程池和套接字。连接

class Program {

    static void Connect(object o)
    {
        IPEndPoint address = (IPEndPoint)o;
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Connect(address);
        Console.WriteLine("Connected {0}", socket.LocalEndPoint);
        socket.Send(Encoding.UTF8.GetBytes("Hello"));
        Console.WriteLine("success");
        socket.Close();
    }

    static void Main(string[] args)
    {
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 5111);
        ThreadPool.QueueUserWorkItem(Connect, endPoint);
        Console.ReadKey();
    }
}
使用BeginConnect(无单独螺纹)

class Program {

static void Main(string[] args)
{
    BeginConnect(new IPEndPoint(IPAddress.Loopback, 5111));
    Console.ReadKey();
}

public static void BeginConnect(IPEndPoint address)
{
    try
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.BeginConnect(address, ConnectCallback, socket);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

private static void ConnectCallback(IAsyncResult ar)
{
    Socket sock = (Socket)ar.AsyncState;
    try
    {
        sock.EndConnect(ar);
        Console.WriteLine("Connected {0}", sock.LocalEndPoint);
        sock.Send(Encoding.UTF8.GetBytes("Hello"));
        Console.WriteLine("success");
        sock.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine("send ex " + ex);
        if (sock != null)
            sock.Close();
    }
}
}
使用带有单独螺纹的BeginConnect:

class Program
{

    static void Main(string[] args)
    {
        Thread t = new Thread(delegate()
        {
            BeginConnect(new IPEndPoint(IPAddress.Loopback, 5111));
        });
        t.Start();
        Console.ReadKey();
    }

    public static void BeginConnect(IPEndPoint address)
    {
        try
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.BeginConnect(address, ConnectCallback, socket);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        Socket sock = (Socket)ar.AsyncState;
        try
        {
            sock.EndConnect(ar);
            Console.WriteLine("Connected {0}", sock.LocalEndPoint);
            sock.Send(Encoding.UTF8.GetBytes("Hello"));
            Console.WriteLine("success");
            sock.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("send ex " + ex);
            if (sock != null)
                sock.Close();
        }
    }
}

是否可能因为您没有等待初始线程,操作系统正在取消I/O请求?如果启动异步I/O的原始线程死亡,Windows将取消I/O请求

在本例中,您从一个线程调用BeginConnect,并让该线程终止,因此I/O被取消。现在,如果在套接字上调用Send()时启动的线程实际上没有死亡,那么可能会出现I/O没有被取消的情况

如果您真的希望这样做,可以尝试以下变化:

       static void Main(string[] args) 
    { 
        Thread t = new Thread(delegate() 
        { 
            IAsyncResult ar = BeginConnect(new IPEndPoint("some address")); 
            // wait for the async connect to finish.
            ar.WaitOne();
        }); 
        t.Start(); 

        Console.ReadKey(); 
    } 

    public static IAsyncResult BeginConnect(IPEndPoint address) 
    { 
        try 
        { 
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            return socket.BeginConnect(address, ConnectCallback, socket); 
        } 
        catch (Exception ex) 
        { 
            Console.WriteLine(ex); 
        } 
        return null;
    } 

您创建的调用BeginConnect的线程在调用BeginConnect后退出。如果不让该线程结束,您是否看到任何不同的行为(API文档注意到,如果调用sock.BeginConnect的线程结束,则会出现问题,但这应该只是以前连接的套接字上的问题)是的,存在差异。正如我所说的,即使在调用Program.BeginConnect后添加一个小睡眠也可以实现这一点。API文档声明:“如果此套接字以前已断开连接,则必须在操作完成之前不会退出的线程上调用BeginConnect。这是基础提供程序的限制。”但正如您所述,这是一个新套接字,以前未断开连接…别傻了,乔治。。。当然,代码不会按原样编译。你以为我会在这里粘贴一个真正的服务器地址吗?!我认为写“someaddress”是一个足够强烈的暗示,这是运行此代码之前需要填充的地方。我知道这些选项,但BeginConnect是从单独的线程调用的。这是应用程序的设计。我在问为什么在这种情况下我会出错。我的第二个例子效果很好。。。您可以将此代码改为使用Thread类。我将示例改为使用Thread类。而且效果很好。我认为问题根本不在Thread类中,而是时间问题。你的代码和我的完全一样,我们得到了不同的结果。问题是,在我的机器上,线程在操作完成之前就存在了。请参阅我与上面nos的讨论。OK。我在自己的机器上复制了这种行为(现在,我正在尝试连接到外部主机)。。。并试图理解为什么这个代码不起作用。你能改用连接方法吗?
       static void Main(string[] args) 
    { 
        Thread t = new Thread(delegate() 
        { 
            IAsyncResult ar = BeginConnect(new IPEndPoint("some address")); 
            // wait for the async connect to finish.
            ar.WaitOne();
        }); 
        t.Start(); 

        Console.ReadKey(); 
    } 

    public static IAsyncResult BeginConnect(IPEndPoint address) 
    { 
        try 
        { 
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            return socket.BeginConnect(address, ConnectCallback, socket); 
        } 
        catch (Exception ex) 
        { 
            Console.WriteLine(ex); 
        } 
        return null;
    }