2010-01-19 19 views
5

का उपयोग करते समय सॉकेट समस्या क्या कोई मुझे बता सकता है कि निम्न कोड क्यों काम नहीं करता है?थ्रेडिंग

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(); 
      } 
     } 
    } 
} 

निर्गम (सॉकेट के स्थानीय अंत बिंदु पर ध्यान दें) है:

Connected 0.0.0.0:28142 
send ex System.Net.Sockets.SocketException: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram 
socket using a sendto call) no address was supplied 
    at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, So 
cketFlags socketFlags) 
    at System.Net.Sockets.Socket.Send(Byte[] buffer) 
    at SocketThreadingTest.Program.ConnectCallback(IAsyncResult ar) in Program.cs:line 44 

पाठ्यक्रम जब मैं एक धागा का उपयोग नहीं करते और BeginConnect फोन के सीधे यह ठीक काम करता है। और भी परेशान बात यह है कि एक थ्रेड जोड़ना। सोना जो काफी लंबा है (1 सेकंड) यह भी ठीक काम करता है। कोई विचार? धन्यवाद।

+1

धागा आपके द्वारा बनाए जाने BeginConnect कॉल बाहर निकालता है। यदि आप उस थ्रेड एंड को नहीं देते हैं तो क्या आप कोई अलग व्यवहार देखते हैं (एपीआई दस्तावेज़ नोट्स थ्रेड कॉलिंग सॉक होने पर समस्याएं हैं। बैजिन कनेक्ट कनेक्ट होता है हालांकि पहले से जुड़े सॉकेट पर केवल एक मुद्दा होना चाहिए) – nos

+0

हां एक अंतर है। जैसा कि मैंने कहा, प्रोग्राम को कॉल करने के बाद भी एक छोटी सी नींद जोड़ना। बेजिन कनेक्ट इस काम को बनाता है। एपीआई दस्तावेज़ कहता है: "यदि यह सॉकेट पहले डिस्कनेक्ट हो गया है, तो BeginConnect को थ्रेड पर कॉल किया जाना चाहिए जो ऑपरेशन पूरा होने तक बाहर नहीं निकलता है। यह अंतर्निहित प्रदाता की सीमा है।" लेकिन जैसा कि आपने कहा है कि यह एक नया सॉकेट है और पहले डिस्कनेक्ट नहीं किया गया है ... – Zvika

उत्तर

0

आपके आईपीईंडपॉइंट में एक बंदरगाह होना चाहिए - मुझे यह भी सुनिश्चित नहीं है कि आपका एंडपॉइंट कैसे संकलित होगा, इसकी आवश्यकता है। आप अपने IPEndAddress से पीछे नहीं पैरामीटर के रूप में बंदरगाह की आपूर्ति या इस प्रकार अपने BeginConnect विधि को संशोधित कर सकते हैं:

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

... जहां [पोर्ट] सर्वर पर सुन बंदरगाह प्रतिनिधित्व करता है।

+1

बेवकूफ जॉर्ज मत बनो ... बेशक कोड संकलित नहीं है। आपने मुझे एक असली सर्वर पता पेस्ट करने की क्या उम्मीद की थी ?! मैंने सोचा कि "कुछ पता" लिखना एक मजबूत संकेत है कि यह एक ऐसा स्थान है जहां आपको इस कोड को चलाने से पहले भरने की आवश्यकता है। – Zvika

+0

आपने गलत सोचा!;) –

1

जो अलग थ्रेड और BeginConnect का उपयोग करने के लिए समझ में आता है? यदि आप अलग थ्रेड बनाते हैं (थ्रेड पूल के साथ अधिमानतः) आप एसिंक्रोनस कनेक्शन का उपयोग क्यों कर रहे हैं (इस मामले में अलग थ्रेड थ्रेड पूल से लिया जाएगा)? उपयोग ThreadPool और Socket.Connect

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(); 
     } 
    } 
} 
+0

मुझे इन विकल्पों के बारे में पता है लेकिन BeginConnect को एक अलग थ्रेड से बुलाया जा रहा है। यह आवेदन का डिजाइन है। मैं पूछ रहा हूं कि इस स्थिति में मुझे एक त्रुटि क्यों मिलती है। – Zvika

+0

मेरा दूसरा उदाहरण अच्छी तरह से काम करता है ... आप इसके बजाय थ्रेड क्लास का उपयोग करने के लिए इस कोड को बदल सकते हैं। –

+0

मैंने थ्रेड क्लास का उपयोग करने के लिए अपना उदाहरण बदल दिया। और यह ठीक काम करता है। मुझे लगता है कि समस्या थ्रेड क्लास में बिल्कुल नहीं है। –

0

यह संभव है कि क्योंकि आप प्रारंभिक थ्रेड के लिए प्रतीक्षा नहीं कर रहे हैं, ओएस आई/ओ के अनुरोध को रद्द किया जाता है? विंडोज़ I/O अनुरोध को रद्द कर देगा यदि मूल धागा जो एसिंक I/O की शुरुआत करता है।

इस मामले में, आप थ्रेड से BeginConnect को कॉल कर रहे हैं, और थ्रेड मरने दे रहे हैं, इसलिए I/O रद्द हो रहा है। अब, ऐसी स्थिति हो सकती है जहां I/O रद्द नहीं हो सकता है यदि आपके द्वारा शुरू किया गया थ्रेड वास्तव में उस समय तक मर नहीं जाता जब आपने सॉकेट पर Send() कहा था।

आप वास्तव में इस काम करना चाहते हैं, तो आपको निम्न भिन्नता की कोशिश कर सकते: BeginConnect कहा जाता है के बाद

 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; 
    } 
संबंधित मुद्दे