2009-04-22 13 views
16

मैं वर्तमान में पायथन में एक टेलनेट सर्वर लिख रहा हूं। यह एक सामग्री सर्वर है। लोग टेलनेट के माध्यम से सर्वर से कनेक्ट होंगे, और टेक्स्ट-केवल सामग्री के साथ प्रस्तुत किए जाएंगे।एकाधिक एक साथ नेटवर्क कनेक्शन - टेलनेट सर्वर, पायथन

मेरी समस्या यह है कि सर्वर को एक से अधिक एक साथ कनेक्शन का समर्थन करने की आवश्यकता होगी। वर्तमान कार्यान्वयन अब मैं केवल एक का समर्थन करता हूं।

यह बुनियादी, सबूत अवधारणा-का-सर्वर मैं के साथ शुरू हुआ है (जबकि कार्यक्रम समय के साथ बहुत बदल गया है, बुनियादी ढांचे टेलनेट नहीं है):

import socket, os 

class Server: 
    def __init__(self): 
     self.host, self.port = 'localhost', 50000 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.socket.bind((self.host, self.port)) 

    def send(self, msg): 
     if type(msg) == str: self.conn.send(msg + end) 
     elif type(msg) == list or tuple: self.conn.send('\n'.join(msg) + end) 

    def recv(self): 
     self.conn.recv(4096).strip() 

    def exit(self): 
     self.send('Disconnecting you...'); self.conn.close(); self.run() 
     # closing a connection, opening a new one 

    # main runtime 
    def run(self): 
     self.socket.listen(1) 
     self.conn, self.addr = self.socket.accept() 
     # there would be more activity here 
     # i.e.: sending things to the connection we just made 


S = Server() 
S.run() 

आपकी मदद के लिए धन्यवाद।

उत्तर

2

यदि आप एक अवधारणात्मक चुनौती के लिए तैयार हैं, तो मैं मुड़ने का उपयोग करना चाहता हूं।

आपके मामले को मुड़ने के एक हिस्से के रूप में लागू करने के लिए तुच्छ होना चाहिए। http://twistedmatrix.com/projects/core/documentation/howto/servers.html

+0

+1 पर

देखो: मुड़ जाने का रास्ता है। एक साधारण टेलनेट सर्वर को कार्यान्वित करना वास्तव में आसान होना चाहिए। – nosklo

4

आपको एसिंक्रोनस सॉकेट आईओ के कुछ रूप की आवश्यकता है। this explanation पर एक नज़र डालें, जो कम स्तरीय सॉकेट शर्तों में अवधारणा पर चर्चा करता है, और संबंधित उदाहरण जो पायथन में लागू होते हैं। यह आपको सही दिशा में इंगित करना चाहिए।

3

एक वास्तव में आसान जीत के लिए आप समाधान SocketServer & का उपयोग कर लागू SocketServer.ThreadingMixIn

एक एक इस गूंज सर्वर उदाहरण यह काफी के समान दिखता है क्या तुम वैसे भी कर रहे हैं देखने के लिए है: http://www.oreillynet.com/onlamp/blog/2007/12/pymotw_socketserver.html

+1

-1: सॉकेटसेवर प्रति कनेक्शन थ्रेड का उपयोग करता है जो वास्तव में एक खराब दृष्टिकोण है। – nosklo

+0

हाँ आप सही हैं, मैंने एक बार एक xmlrpc सर्वर बनाया है जो एक्सेल से vba फ़ंक्शंस के माध्यम से बात की जाती है जिसे xmlrpc सेवा कहा जाता है। यह तब तक अच्छा काम करता है जब तक कि किसी ने 1000 पंक्तियों के नीचे एक सूत्र को भर दिया, जिस बिंदु पर परिभाषित फ़ंक्शन जिसे मेरी xmlrpc सेवा 1000 बार कहा जाता है, 1000 धागे बनाते हैं। मज़ा नहीं। घुमावदार दृष्टिकोण निश्चित रूप से जाने का रास्ता है। – Ravi

16

में लागू twisted:

from twisted.internet.protocol import Factory, Protocol 
from twisted.internet import reactor 

class SendContent(Protocol): 
    def connectionMade(self): 
     self.transport.write(self.factory.text) 
     self.transport.loseConnection() 

class SendContentFactory(Factory): 
    protocol = SendContent 
    def __init__(self, text=None): 
     if text is None: 
      text = """Hello, how are you my friend? Feeling fine? Good!""" 
     self.text = text 

reactor.listenTCP(50000, SendContentFactory()) 
reactor.run() 

परीक्षण:

$ telnet localhost 50000 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
Hello, how are you my friend? Feeling fine? Good! 
Connection closed by foreign host. 

गंभीरता से, जब यह असीमित नेटवर्क की बात आती है, तो मुड़ने का रास्ता है। यह एकल-थ्रेड सिंगल-प्रोसेस दृष्टिकोण में एकाधिक कनेक्शन को संभालता है।

+1

यह सही है। क्या आप क्लाइंट से डेटा भेजने और प्राप्त करने का उदाहरण दे सकते हैं? मैं ट्विस्ट पर पढ़ रहा हूं लेकिन यह ट्यूटोरियल्स में काफी वर्बोज़ है। – SpleenTea

+1

@SpleenTea: बस एक डेटा जोड़ें प्रोटोकॉल पर प्राप्त विधि और डेटा इसके लिए जाएगा। यदि आपका प्रोटोकॉल लाइन-आधारित है, तो आप प्रोटोकॉल के बजाय twisted.protocols.basic.LineReceiver उपclass करना चाह सकते हैं, ताकि आप लाइन को परिभाषित कर सकें और इसे क्लाइंट से प्राप्त होने वाली प्रत्येक पंक्ति के लिए बुलाया जाएगा। जैसा कि मैंने ऊपर दिए गए उदाहरण में किया है, केवल self.transport.write का उपयोग करने के लिए। http://twistedmatrix.com/projects/core/documentation/howto/ बहुत उपयोगी है, विशेष रूप से ट्यूटोरियल। – nosklo

1

यदि आप इसे शुद्ध पायथन (सैन्स-ट्विस्ट) में करना चाहते हैं, तो आपको कुछ थ्रेडिंग करने की आवश्यकता है। इससे पहले कि आप इसे देखा havnt, तो यह देखें: http://heather.cs.ucdavis.edu/~matloff/Python/PyThreads.pdf

पेज 5/6 चारों ओर एक उदाहरण यह है कि बहुत प्रासंगिक है;)

+0

-1: आलेख धागे के बारे में एक सामान्य लेख है। उदाहरणों में सॉकेट के साथ कुछ लेना देना नहीं है। धागे के साथ एक अच्छा सॉकेट सर्वर कार्यान्वित करना मुश्किल है, इसमें बहुत सारे विवरण हैं और डीबग करना मुश्किल है, और आपको कोई फायदा नहीं होता है। एसिंक्रोनस नहीं जाने का कोई कारण नहीं है। – nosklo

+1

पी.5 (srvr.py) के नीचे एक सर्वर है जो सॉकेट इंटरफेस का उपयोग बंदरगाह से बांधने और कनेक्शन सुनने के लिए करता है। आप सही हे। सॉकेट की वर्तमान चर्चा के साथ इसका कोई लेना-देना नहीं है। मेरी गलती। – Alex

1

पहले, TCP/IP programming पर आगंतुक की किताबें खरीदते हैं।

उन पुस्तकों में, कॉमर सर्वर के लिए कई वैकल्पिक एल्गोरिदम प्रदान करेगा। दो मानक दृष्टिकोण हैं।

  • थ्रेड-प्रति-अनुरोध।

  • प्रक्रिया-प्रति-अनुरोध।

आपको इन दोनों में से एक को चुनना होगा और इसे लागू करना होगा।

थ्रेड-प्रति में, प्रत्येक टेलनेट सत्र आपके समग्र एप्लिकेशन में एक अलग धागा है।

प्रक्रिया-प्रति में, आप प्रत्येक टेलनेट सत्र को एक अलग उपप्रोसेक में फोर्क करते हैं।

आप पाएंगे कि प्रक्रिया-प्रति-अनुरोध Python में संभालने के लिए बहुत आसान है, और यह आमतौर पर आपके सिस्टम का अधिक कुशल उपयोग करता है।

थ्रेड-प्रति-अनुरोध उन चीजों के लिए ठीक है जो जल्दी आते हैं और जल्दी जाते हैं (जैसे HTTP अनुरोध)। टेलनेट में लंबे समय से चलने वाले सत्र हैं जहां एक उपप्रोसेसर के लिए स्टार्टअप लागत प्रदर्शन पर हावी नहीं है।

+0

-1: थ्रेड-प्रति-अनुरोध और प्रक्रिया-प्रति-अनुरोध दोनों एक साथ अनुरोधों की संख्या को स्केल नहीं कर सकते हैं। – nosklo

+2

@ नोस्क्लो: "कुछ संख्या" कुछ संख्याओं के लिए कुछ भी स्केल नहीं कर सकता क्योंकि वे बहुत विशाल हैं। प्रति अनुरोध थ्रेड अक्सर काफी स्केलेबल माना जाता है। क्या आपके पास विकल्प हैं कि विकल्प क्या हैं? –

+0

प्रत्येक अनुरोध के लिए अपने concurrency मॉडल को टाई मत करो। इसके बजाय, अनुरोधों की संख्या से स्वतंत्र कई प्रक्रियाओं/धागे चलाएं। उसी प्रक्रिया/थ्रेड में कई अनुरोधों के साथ सौदा करें, अधिमानतः एसिंक IO का उपयोग करके। वह तराजू बेहतर तरीका है। – nosklo

4

उत्तर के लिए देर हो चुकी है, लेकिन केवल उत्तर के साथ ट्विस्ट या थ्रेड्स (आउच) होने के साथ, मैं मिनीबाआ के लिए एक उत्तर जोड़ना चाहता था।

http://code.google.com/p/miniboa/

मुड़ महान है, लेकिन यह एक नहीं बल्कि बड़े जानवर कि एकल पिरोया अतुल्यकालिक टेलनेट प्रोग्रामिंग करने के लिए सबसे अच्छा परिचय नहीं हो सकता है। मिनीबाआ एक हल्का, असीमित एकल-थ्रेडेड पायथन टेलनेट कार्यान्वयन मूल रूप से मिट्टी के लिए डिज़ाइन किया गया है, जो ओपी के सवाल को पूरी तरह से उपयुक्त बनाता है।

1

मिनीबाआ सर्वर आज़माएं? इसमें बिल्कुल 0 निर्भरताएं हैं, कोई मोड़ या अन्य सामान की आवश्यकता नहीं है। मिनीबाआ एक गैर-अवरुद्ध एसिंक टेलनेट सर्वर है, एकल थ्रेडेड, बिल्कुल वही है जो आपको चाहिए।

http://code.google.com/p/miniboa/

1

उपयोग सूत्रण और उसके बाद एक समारोह में हैंडलर जोड़ने। धागा हर बार एक अनुरोध मैंने बनाया कॉल करेगा: इस

import socket    # Import socket module 
import pygame 
import thread 
import threading,sys 

s = socket.socket()   # Create a socket object 
host = socket.gethostname() # Get local machine name 
port = 12345    # Reserve a port for your service. 
s.bind((host, port)) 
print ((host, port)) 
name = "" 
users = [] 

def connection_handler (c, addr): 
     print "conn handle" 
     a = c.recv (1024) 
     if a == "c": 
     b = c.recv (1024) 
     if a == "o": 
     c.send (str(users)) 
     a = c.recv (1024) 
     if a == "c": 
      b = c.recv (1024) 
     print a,b 






s.listen(6)     # Now wait for client connection. 
while True: 
    c, addr = s.accept() 
    print 'Connect atempt from:', addr[0] 
    username = c.recv(1024) 
    print "2" 
    if username == "END_SERVER_RUBBISH101": 
     if addr[0] == "192.168.1.68": 
     break 
    users.append(username) 
    thread.start_new_thread (connection_handler, (c, addr)) #New thread for connection 

print 
s.close() 
संबंधित मुद्दे