2009-06-20 11 views
10

मैं नेटवर्क प्रोग्रामिंग का अध्ययन करता हूं और पाइथन में एक साधारण कमांड लाइन चैट लिखना चाहता हूं।पायथन में एक साधारण कमांड लाइन चैट कैसे करें?

मैं सोच रहा हूं कि किसी भी समय भेजने के लिए उपलब्ध इनपुट के साथ लगातार कैसे प्राप्त करना है।

जैसा कि आप देख, यह ग्राहक एक समय में केवल एक ही काम कर सकते हैं:

from socket import * 

HOST = 'localhost' 
PORT = 21567 
BUFSIZE = 1024 
ADDR = (HOST, PORT) 

tcpCliSock = socket(AF_INET, SOCK_STREAM) 
tcpCliSock.connect(ADDR) 

while 1: 
    data = raw_input('> ') 
    if not data: break 
    tcpCliSock.send(data) 
    data = tcpCliSock.recv(BUFSIZE) 
    if not data: break 
    print data 

tcpCliSock.close() 

तो एक और ग्राहक एक संदेश भेजता है, तो यह ग्राहक केवल यह भी एक संदेश भेजने के बाद प्राप्त होगा। मुझे यकीन है कि तुम मुझे समझते हो। मैंने इस मामले के लिए गुमराह किया है और कई दिलचस्प चीजें जैसे कि एसिंक्रोनस आई/ओ, थ्रेडिंग, गैर-अवरुद्ध सिंक्रनाइज़ेशन, समवर्ती प्रोग्रामिंग आदि शामिल हैं। मैंने ट्विस्ट पैकेज भी स्थापित किया है। संक्षेप में, मैं इन सभी चीजों को सीख रहा हूं लेकिन फिर भी वह नहीं मिला जो मैं ढूंढ रहा था। (बेशक, मैं कोशिश करता हूं और कोशिश करता हूं जब तक कि मैं बिंदु तक नहीं पहुंच जाता।)

तो, मेरा सवाल यह है कि यह कैसे बनाते हैं? =)

उत्तर

5

यदि आप इसे स्क्रैच से कोड करना चाहते हैं select जाने का तरीका है (और आप Google पुस्तक खोज पर पाइथन के अधिकांश अध्याय में पढ़ सकते हैं जो संक्षेप में ऐसे मामलों को शामिल करता है); यदि आप अधिक अमूर्तता का लाभ उठाना चाहते हैं, तो asyncore उपयोग योग्य है, लेकिन Twisted अधिक समृद्ध और अधिक शक्तिशाली है।

1

मैं async में एक ने लिखा है मैं/हे ... इसके बहुत आसान अपने सिर के चारों ओर एक पूर्ण सूत्रण मॉडल की तुलना में रैप करने के लिए।

यदि आप अपने हाथों को "टॉक" स्रोत कोड की पकड़ प्राप्त कर सकते हैं, तो आप इसके बारे में बहुत कुछ सीख सकते हैं। एक डेमो http://dsl.org/cookbook/cookbook_40.html#SEC559 देखें, या यदि आप लिनक्स बॉक्स पर हैं तो इसे अपने आप आज़माएं ...

यह वास्तविक समय में वर्ण भेजता है।

भी, ytalk इंटरैक्टिव और एकाधिक उपयोगकर्ता है .... थोडा हडडलेचैट या कैम्पफायर की तरह।

2

चैट प्रोग्राम दो चीजें एक साथ कर रहे हैं।

  1. स्थानीय उपयोगकर्ता के कीबोर्ड देखना और (किसी तरह की एक सॉकेट के माध्यम से) दूरस्थ उपयोगकर्ता के लिए भेजने से

  2. दूरस्थ सॉकेट देखना है और क्या वे स्थानीय कंसोल पर टाइप प्रदर्शित।

आपके पास ऐसा करने के कई तरीके हैं।

  1. एक कार्यक्रम सॉकेट और कीबोर्ड को खोलता है और जो एक इनपुट तैयार है देखने के लिए select मॉड्यूल का उपयोग करता है।

  2. एक प्रोग्राम जो दो धागे बनाता है।एक धागे रिमोट सॉकेट और प्रिंट पढ़ता है। दूसरा धागा कुंजीपटल पढ़ता है और रिमोट सॉकेट भेजता है।

  3. एक प्रोग्राम जो दो उपप्रोसेसरों को फोर्क करता है। एक subprocess रिमोट सॉकेट और प्रिंट पढ़ता है। अन्य उपप्रोसेसर कीबोर्ड पढ़ता है और रिमोट सॉकेट भेजता है।

+0

http://docs.python.org/library/select.html मैंने कभी भी पढ़ा है कि खराब दस्तावेज़ है। कोई उदाहरण नहीं हैं! मुझे उस स्रोत से कुछ भी नहीं मिला ... – user122922

+0

ठीक है, फिर कहीं और चुनें एपीआई के बारे में पढ़ें। http://linux.die.net/man/2/select। http://www.cs.utah.edu/~swalton/listings/sockets/programs/। Google काम करता है। –

+0

http://docs.python.org/howto/sockets.html#non-blocking-sockets –

2

ठीक है, ठीक है, इस समय मैं यहां क्या कर रहा हूं।

सर्वर इस प्रकार है:

import asyncore 
import socket 

clients = {} 

class MainServerSocket(asyncore.dispatcher): 
    def __init__(self, port): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.bind(('',port)) 
     self.listen(5) 
    def handle_accept(self): 
     newSocket, address = self.accept() 
     clients[address] = newSocket 
     print "Connected from", address 
     SecondaryServerSocket(newSocket) 

class SecondaryServerSocket(asyncore.dispatcher_with_send): 
    def handle_read(self): 
     receivedData = self.recv(8192) 
     if receivedData: 
      every = clients.values() 
      for one in every: 
       one.send(receivedData+'\n') 
     else: self.close() 
    def handle_close(self): 
     print "Disconnected from", self.getpeername() 
     one = self.getpeername() 
     del clients[one] 

MainServerSocket(21567) 
asyncore.loop() 

और ग्राहक सिर्फ इस प्रकार है:

from Tkinter import * 
from socket import * 
import thread 

HOST = 'localhost' 
PORT = 21567 
BUFSIZE = 1024 
ADDR = (HOST, PORT) 

tcpCliSock = socket(AF_INET, SOCK_STREAM) 
tcpCliSock.connect(ADDR) 

class Application(Frame): 
    def __init__(self, master): 
     Frame.__init__(self, master) 
     self.grid() 
     self.create_widgets() 
     self.socket() 

    def callback(self, event): 
     message = self.entry_field.get() 
     tcpCliSock.send(message) 

    def create_widgets(self): 
     self.messaging_field = Text(self, width = 110, height = 20, wrap = WORD) 
     self.messaging_field.grid(row = 0, column = 0, columnspan = 2, sticky = W) 

     self.entry_field = Entry(self, width = 92) 
     self.entry_field.grid(row = 1, column = 0, sticky = W) 
     self.entry_field.bind('<Return>', self.callback) 

    def add(self, data): 
     self.messaging_field.insert(END, data) 

    def socket(self): 
     def loop0(): 
      while 1: 
       data = tcpCliSock.recv(BUFSIZE) 
       if data: self.add(data) 

     thread.start_new_thread(loop0,()) 



root = Tk() 
root.title("Chat client") 
root.geometry("550x260") 

app = Application(root) 

root.mainloop() 

अब यह कोड बनाने के लिए समय बेहतर देखने के लिए और कुछ कार्यक्षमता जोड़ने है।

आपकी मदद के लिए धन्यवाद, दोस्तों!

+0

ओह, मैं कमांड लाइन चैट के बारे में बात कर रहा था लेकिन एक जीयूआई ऐप के साथ समाप्त हुआ। हालांकि, यह चीजों को अलग नहीं करता है। – user122922

8

आपका प्रश्न बहुत सुसंगत नहीं था। हालांकि, आप जो भी मांग रहे हैं उसे प्राप्त करने के लिए आपके कार्यक्रम को असीमित होने की आवश्यकता नहीं है।

यह एक कामकाजी चैट स्क्रिप्ट है जिसे आप मूल रूप से न्यूनतम परिवर्तनों के साथ चाहते थे। यह ब्लॉकिंग सॉकेट का उपयोग करके, प्राप्त करने के लिए 1 धागा और भेजने के लिए 1 का उपयोग करता है। यह एसिंक्रोनस विधियों का उपयोग करने से कहीं अधिक सरल है।

from socket import * 
from threading import Thread 
import sys 

HOST = 'localhost' 
PORT = 21567 
BUFSIZE = 1024 
ADDR = (HOST, PORT) 

tcpCliSock = socket(AF_INET, SOCK_STREAM) 
tcpCliSock.connect(ADDR) 

def recv(): 
    while True: 
     data = tcpCliSock.recv(BUFSIZE) 
     if not data: sys.exit(0) 
     print data 

Thread(target=recv).start() 
while True: 
    data = raw_input('> ') 
    if not data: break 
    tcpCliSock.send(data) 

tcpCliSock.close() 
+0

> यह एसिंक्रोनस विधियों का उपयोग करने से कहीं अधिक सरल है। हे, दोस्त, मैं अपने चैट क्लाइंट में किसी भी एसिंक्रोनस विधियों का उपयोग कहां करूं? (ठीक है, मुझे सर्वर की परवाह नहीं है; मैं ग्राहकों में दिलचस्प था।) मेरा चैट क्लाइंट आपके जैसा ही है, सिवाय इसके कि आप थ्रेडिंग मॉड्यूल आयात करते हैं, और मैं थ्रेड मॉड्यूल आयात करता हूं। हालांकि, धन्यवाद! – user122922

+0

अंतर यह है कि आपने एसिंकोर आयात किया है, इसलिए आपने एसिंक्रोनस विधियों का उपयोग किया था। इसके अलावा आप एक पूरी अनावश्यक जीयूआई भी शामिल थे, लेकिन इसके अलावा यह वही है। – Unknown

+0

एसिंककोर मॉड्यूल को सर्वर ऐप में आयात किया गया था, क्लाइंट ऐप में नहीं। Да и фиг с ним ... – user122922

संबंधित मुद्दे