सी

2012-05-16 4 views
17

में सॉकेट कनेक्शन को पूरी तरह से कैसे नष्ट करें मैंने सॉकेट का उपयोग करके लिनक्स में चैट क्लाइंट बनाया है, और मैं कनेक्शन को पूरी तरह से नष्ट करना चाहता हूं। पीछा कर रहा है कोड के प्रासंगिक अंश:सी

int sock, connected, bytes_recieved , true = 1, pid; 
char send_data [1024] , recv_data[1024];  
struct sockaddr_in server_addr,client_addr;  
int sin_size; 
label: 
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
{ 
    perror("Socket"); 
    exit(1); 
} 
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) 
{ 
    perror("Setsockopt"); 
    exit(1); 
} 
server_addr.sin_family = AF_INET;   
server_addr.sin_port = htons(3128);  
server_addr.sin_addr.s_addr = INADDR_ANY; 
bzero(&(server_addr.sin_zero),8); 
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) 
{ 
    perror("Unable to bind"); 
    exit(1); 
} 
if (listen(sock, 5) == -1) 
{ 
    perror("Listen"); 
    exit(1); 
} 
printf("\nTCPServer Waiting for client on port 3128"); 
fflush(stdout); 
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); 
//necessary code 
close(sock); 
goto label; 

लेकिन करीब (जुर्राब) क्योंकि 'लेबल' कोड त्रुटि संदेश

दिखा बाहर निकलने है जाने के बाद, पूरी तरह से कनेक्शन को नष्ट बंद करने के लिए doesnot लगते
Unable to bind: Address already in use 

यह कनेक्शन फिर से नहीं हो रहा है। समस्या क्या हो सकती है? अग्रिम में धन्यवाद।

संपादित करें: मैं वास्तव में क्या चाहता हूं, जब मैं कनेक्शन को नष्ट करने के बाद शुरुआत से स्क्रिप्ट चलाता हूं, तो इसे एक नए कार्यक्रम के रूप में चलाया जाना चाहिए। मैं यह कैसे कर सकता हूं?

+0

आप ऐसा क्यों कर रहे हैं? आपको 'स्वीकृति' से पहले लूप करना चाहिए, सर्वर सॉकेट को दोबारा नहीं बनाना चाहिए। – Mat

+0

आप 'स्वीकार()' के आसपास लूपिंग के बजाय सुनवाई सॉकेट को बंद और फिर से खोलना क्यों चाहते हैं? – dwalter

+0

संभावित डुप्लिकेट [SO_REUSEADDR (सेटॉकोपट विकल्प) का अर्थ क्या है - लिनक्स?] (Http://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option- लिनक्स) –

उत्तर

24

close कॉल केवल टीसीपी सॉकेट बंद करता है। यह अब प्रक्रिया से प्रयोग योग्य नहीं है। लेकिन कर्नेल अभी भी एक अवधि (TIME_WAIT, 2MLS आदि सामान) के लिए कुछ संसाधन रख सकता है।

SO_REUSEADDR की स्थापना बाध्यकारी समस्याओं को दूर करना चाहिए।

तो सुनिश्चित करें कि true का मूल्य वास्तव में गैर शून्य जब setsockopt (अतिप्रवाह बग यह ओवरराइट कर सकता है) पर कॉल है:

true = 1; 
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) 

वहाँ pid चर अपने कोड है। यदि आप fork (कनेक्शन हैंडलिंग प्रक्रिया शुरू करने के लिए) का उपयोग करते हैं, तो आपको उस प्रक्रिया में sock भी बंद करना चाहिए, जिसकी आवश्यकता नहीं है।

-1

ठीक है, क्योंकि एक कनेक्शन वास्तव में बंद होता है जब दूसरी पार्टी इसे स्वीकार करती है या एक निश्चित टाइमआउट के बाद। यह ... सामान्य व्यवहार है

संपादित करें: मैं वास्तव में अपने कोड की जांच नहीं की, बल्कि अन्य उपयोगकर्ताओं की टिप्पणियों से, आप कुछ गलत कर रहे हैं ...

0

आप shutdown(2) सिस्टम कॉल का उपयोग करना चाहिए।

+1

मैंने कोशिश की है लेकिन अभी भी कोई भाग्य नहीं है। कनेक्शन नष्ट नहीं हो रहा है। –

1

nameing के लिए सबसे पहले है, इसलिए हम सभी नाम एक ही बातें एक ही:

सर्वर साइड:

सॉकेट listen() को पारित कर दिया और उसके बाद accept() करने के सुनने सॉकेट फोन करते हैं। सॉकेट accept() द्वारा लौटाया गया है स्वीकृत सॉकेट को कॉल करें।

क्लाइंट साइड:

सॉकेट connect() के लिए पारित के जोड़ने/जुड़े सॉकेट फोन करते हैं।


आपकी समस्या के बारे में:

accept() एड कनेक्शन पहले shutdown()close() के बाद का उपयोग करके बंद स्वीकार किए जाते हैं सॉकेट (आप क्या कॉल कनेक्ट हो) को समाप्त करने के लिए। फिर accept() पर कॉल करने से पहले एक नया कनेक्शन लूप स्वीकार करने के लिए, bind() और listen() से फिर से जाएं।

केवल बंद और सुन सॉकेट बंद आप लंबित accept() लौटे के बाद जारीconnect() रों से छुटकारा पाने के लिए करना चाहते हैं।

1

कनेक्शन अभी भी सक्रिय है क्योंकि आप कनेक्ट सॉकेट को बंद करना भूल गए हैं। सुनना सॉकेट बंद करना स्वचालित सॉकेट को स्वचालित रूप से बंद नहीं करता है।

//necessary code 
close(connected); // <---- add this line 
close(sock); 
goto label; 

मुझे यकीन नहीं है कि आप EADDRINUSE क्यों प्राप्त कर रहे हैं। कोड लिनक्स और मैक ओएस दोनों पर ठीक काम करता है।