Author Topic: Networking الشبكات  (Read 695 times)

Ahmed Youssef

  • Helping Freak
  • Administrator
  • Active Member
  • *****
  • Posts: 242
    • View Profile
    • WWW
    • Email
Networking الشبكات
« on: January 11, 2009, 03:05:22 PM »
Networking




فصل اكبر من ان يغطيه كتاب مثل هذا و لمقدمة عن ال sockets راجع مقالة ويكيبديا
http://en.wikipedia.org/wiki/Internet_socket



سرفر بسيط
Code: [Select]
 #simpleserver.py
import socket

class EchoServer(object):

def __init__(self, host='', port=51002):
self._host, self._port=host, port
self._endpoint=(host, port) #host, addr
self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

def start(self):
self.sock.bind(self._endpoint)
self.sock.listen(1)
print "Server running on: ", self._port
self.handle_request()

def handle_request(self):

while True: #Waits for a client.
clientsock, addr=self.sock.accept()
#clientfile=clientsock.makefile('rw', 0) #Create a file-like object.
print "Connection from: ", addr

clientsock.sendall(str(addr)+" you are connected to server...")

while True: #communication loop



#clientfile.write(str(addr)+" you are connected to server.\n")
msg=clientsock.recv(8092)
if msg:
print ">> ", msg
clientsock.sendall(msg)
#msg=clientfile.readline().strip() #clean it up.
#print "Recieved: ", msg
#clientfile.write("Got: "+msg+"\n")

#Cleaning UP
#clientfile.close()
clientsock.close()




if __name__=="__main__":
try:
es=EchoServer()
es.start()
except KeyboardInterrupt:
exit()


فى هذا الكود انشأنا صف جديد بإسم EchoServer
Code: [Select]
class EchoServer(object): 

def __init__(self, host='', port=51002):
self._host, self._port=host, port
self._endpoint=(host, port) #host, addr
self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
 

1- قمنا بتحديد ال endpoint (الهوست والبورت)
2- انشأنا TCP Socket
3- قمنا بتفعيل استخدام SO_REUSEADDR لإلغاء شغل البورت عنده ايقاف السرفر
(بتفيد عند الحاجة لعمل ريستارت)

قمنا بتعريف طريقة start لبدأ السرفر
Code: [Select]
 	def start(self): 
self.sock.bind(self._endpoint)
self.sock.listen(1)
print "Server running on: ", self._port
self.handle_request()

1- عمل bind (ربط بال endpoint اللتى تم تحديدها)
2- تجهيز وتشغيل ال tcp listener بإستخدام الطريقة listen
3- نستدعى الطريقة handle_request اللتى سيتم فيها التعامل مع العميل
مكونة من حلقتين الأولى للتعامل مع العملاء المنتظرين والثانية لمعالجة عميل ما
Code: [Select]
	def handle_request(self): 

while True: #Waits for a client.
clientsock, addr=self.sock.accept()
#clientfile=clientsock.makefile('rw', 0) #Create a file-like object.
print "Connection from: ", addr

clientsock.sendall(str(addr)+" you are connected to server...")

while True: #communication loop


msg=clientsock.recv(8092)
if msg:
print ">> ", msg
clientsock.sendall(msg)

#Cleaning UP
clientsock.close()


الطريقة accept تقبل اتصالا وتعيد لنا كائن socket وعنوان
تستطيع استخدام الطريقة makefile لإنشاء file-like object للتعامل مع ال socket
الطريقة sendall لإرسال رسالة
الطريقة recv للحصول على الرسالة القادمة (ويتم تحديد حجمها عن طريق معامل ال bufsize)


كلاينت بسيط
Code: [Select]
#simpleclient.py
import socket

class SimpleClient(object):

def __init__(self, endpoint=('127.0.0.1', 51002)):
self._endpoint=endpoint
self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(self._endpoint)

def start(self):

while True:

data=self.sock.recv(8096)
if not data:
break
print data

msg=raw_input("> ")
if not msg:
break
self.sock.send(msg)
self.sock.close()



if __name__=="__main__":
try:
sc=SimpleClient()
sc.start()
except KeyboardInterrupt:
exit() 

هنا انشأنا صف جديد SimpleClient
Code: [Select]
 	class SimpleClient(object): 

def __init__(self, endpoint=('127.0.0.1', 51002)):
self._endpoint=endpoint
self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(self._endpoint)

نقوم بعمل اتصال مع السرفر (تحديد ال endpoint) بإستخدام الطريقة connect
   
الطريقة start تقوم بعمل حلقة الإتصال مع السرفر
Code: [Select]
	def start(self): 

while True:

data=self.sock.recv(8096)
if not data:
break
print data

msg=raw_input("> ")
if not msg:
break
self.sock.send(msg)
self.sock.close()

الخ الخ

SocketServer
هى موديل فيها تجميع للصفات الشائعة فمثلا لاحاجة لكتابة الأكواد السابقة لمجرد انشاء TCPServer او UDPServerوهكذا ولكن الأساس ثابت وهناك بعض المتغيرات اللتى يمكن اعادة تعريفها (التعامل مع العميل على سبيل المثال)
سرفر
Code: [Select]
 #!/usr/bin/env python 
#-*- coding:utf-8 -*-

from SocketServer import TCPServer, StreamRequestHandler

class MyStreamRequestHandler(StreamRequestHandler):

def handle(self):
print "Got connection from: ", self.client_address
self.wfile.write(str(self.client_address)+" you are connected to server.")
#Communication loop...


while True:

msg=self.request.recv(1024)
if not msg:
break
print ">> ", msg
#Send it back...
self.request.send(msg)
print "Done handling..."


def go(endpoint=('', 52002)):
addr=endpoint
tcpServer=TCPServer(addr, MyStreamRequestHandler)
tcpServer.allow_reuse_address=1
print "Server started..."
tcpServer.serve_forever() #inf. loop

if __name__=="__main__":
try:
go()
except KeyboardInterrupt:
exit()
هنا نشتق صف من ال StreamRequestHandler ويتم اعادة تعريف الطريقة handle اللتى يتم تنفيذها عند اتصال اى عميل
ولإنشاء السرفر نقوم بإستدعاء الصف TCPServer ونمرر له العنوان وايضا الصف الخاص بالتعامل مع طلب العميل MyStreamRequestHandler
ونتيح ايضا امكانية استخدام العنوان بإستخدام allow_reuse_address
ويبدأ السرفر فى العمل بإستخدام الطريقة serve_forever
كلاينت


Code: [Select]
import socket

class SimpleClient(object):

def __init__(self, endpoint=('127.0.0.1', 52002)):
self._endpoint=endpoint
self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(self._endpoint)

def start(self):
#self.sock.sendall("Hey you!!")
while True:

data=self.sock.recv(1024)
if not data:
break
print data

msg=raw_input("> ")
if not msg:
break

self.sock.sendall(msg)
#self.sock.close()



if __name__=="__main__":
try:
sc=SimpleClient()
sc.start()
except KeyboardInterrupt:
exit()


 

MixIns
تستطيع بكل سهولة ان تجعل سرفرك يعالج اكثر من عميل سواء بإستخدام ال Threading او ال Forking
وذلك بإشتقاقك لل ThreadingMixIn او ال ForkingMixIn الموجودة فى SocketServer module
Code: [Select]
class MyServer(ThreadingMixIn,TCPServer): 
pass #Done!

او هكذا
Code: [Select]
class MyServer(ForkingMixIn, TCPServer): 
pass #Done!

الفرق ان ال Forking يتم معالجة كل عميل فى بروسيس جديدة بينما ال Threading يتم معالجتها داخل نفس العملية ولكن بخيط جديد (تعدد مهام مثل محرر النصوص اللذى تكتب فيه ويقوم بالترقيم وتصحيح الأخطاء الإملائية والعديد من هذه العمليات فى ان واحد)

تطبيق دردشة


السرفر
Code: [Select]
#!bin/python 

import socket
import threading


class ChatServer(object):
    '''Indexer...'''

    def __init__(self, port):
       
        self.port=port
        addr=('', self.port)
        self._bufsize=2048
       
        self.listener=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #Quick restarts.
        self.listener.bind(addr)
        self.alSocks=[]
        #self.tListening=threading.Thread(target=self.listeningHandler, args=[])
        #self.tListening.start()

self.listeningHandler() #Start listening...


       

    def listeningHandler(self):
        self.listener.listen(5)
        print "Server started.."
        while True:
            clientSocket, clientAddr=self.listener.accept()
            #Handle the client in a new thread...
            self.tHandleClient=threading.Thread(target=self.clientHandler, args=[clientSocket])
            self.tHandleClient.start()

           
    def clientHandler(self, clientSocket):
   
        self.alSocks += [clientSocket]
        print "connection from: ", clientSocket.getpeername()
        self._bufsize=2048
        try:
            while True:
               
                data=clientSocket.recv(self._bufsize)
                if not data:
                    break
                #handle sending all recieved in another thread..
                #serverToAll=threading.Thread(target=self.serverToAll, args=[clientSocket, data])
                #serverToAll.start()
                self.serverToAll(clientSocket, data)
               
        except Exception:
            #don't act
            print clientSocket.getpeername(), " closed..."
        finally:
            self.alSocks.remove(clientSocket)
            clientSocket.close()

    def serverToAll(self, currentClient, data):
        try:
            for sock in self.alSocks:
                if not sock == currentClient:
                    sock.send(data)
                else:
                    pass
        except Exception, e:
            print e
           

if __name__=="__main__":

    chatServer=ChatServer(8030) 

   
    ملحوظة لأنشاء خيط جديد فى برنامجك قم بإستخدام الصف threading.Thread لأنشاء كائن وقم بتحديد ال target وهى الميثود اللتى سيتم تنفيذها بصورة خارجية فى ذلك الثريد و args هى عبارة عن list تحوى المعاملات (args) الخاصة بتلك الميثود

الكلاينت
Code: [Select]
#!bin/python 

import socket
import threading


class Peer(object):

    def __init__(self, serverAddr=('localhost', 8030), alias="anonymouse"):
               
                self.serverAddr=serverAddr
                self.tcpClient=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.alias=alias
                self._bufsize=2048
                self.tcpClient.connect(self.serverAddr)
               
                print "\nConnected to server.."
                #self.tClientToServer=threading.Thread(target=self.clientToServerHandler, args=[])
                #self.tClientToServer.start()
              self.clientToServerHandler()
             
    def clientToServerHandler(self):
                print "Start Chattin' \n"
                while True:
               
                    data=raw_input()
                    msg=alias+": "+data
                    if not data:
                        break
                    serverToClient=threading.Thread(target=self.serverToClientHandler, args=[])
                    serverToClient.start()
                    #self.serverToClientHandler()

                    self.tcpClient.send(msg)
 
   

                 
    def serverToClientHandler(self):
   
                while True:
                    data=self.tcpClient.recv(self._bufsize)
                    if not data:
                        break
                    print data
                   

if __name__=="__main__":

                alias=raw_input("Alias: ")
                peer=Peer(alias=alias)
               

               
« Last Edit: September 08, 2009, 08:21:42 PM by Ahmed Youssef »
Logged

Life is just a chance to grow a soul. - A. Powell
Weblog: http://ahmedyoussef.wordpress.com/