Socket en Python

Embed Size (px)

Citation preview

socketsenpython

IntroduccionalossocketsProgramarenredconpythonpuedecaeren2categorias,usarunmodulodeprotocolooprogramar elprotocolodesdecero. Lossocketssonunaextensiondelsistemadeentrada/salidadelsistemaoperativoquepermitela comunicacionentreprocesosymaquinas. Unsocketpermiteusarllamadasdelsistemaoperativoparahablarconotrasmaquinay/oprocesos sobrelamaquinaqueloshallamado. Algunasllamadasalsistemaen*nixquefuncionancondescriptoresdeficheronincluyenaopen(), read(),write(),close().Undescriptordeficherotipicamenterefiereaunficheroounaentidadde tipofichero;puedenser,directorios,bloques,socket,FIFO's. Pythonproveeunainterfacedesocketdelsistemaoperativo,elmodulosocket,siesquesepiensa disearelprotocolodesdecero. Creacindeunsocket Lacreacindeunsocketesdiferentedeunclienteaunserver. Creacindeuncliente Primero,setienequecrearelobjetosocket,luegoseletienequedefinirlafamiliadelprotocolo (comosertransmitidaladata),yeltipodesocket(protocolousadoparatransmitirladata). Familiasdeprocolo:socket.AF_UNIX,socket.AF_INET,socket.AF_INET6 Tipodesocket:socket.SOCK_STREAM,socket.SOCK_DGRAM,socket.SOCK_RAW, socket.SOCK_RDM,socket.SOCK_SEQPACKET Segundo,hayqueconectarelobjetosocketalservidorremoto.Elmtodoconnect()enviaunatupla conteniendoelhostremoto|direccinIPyelpuertoremoto. host="www.example.com" port=80 #Creaciondelobjetosocket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#Conectandolohaciaunhostremoto s.connect(host,port) Creacindeunserver Lacreacindeunserveresparecidoaldeuncliente.Primerosetienequecrearelobjetosocket, luegoaadirlasopcionesdesocketsetsockopt();adems,setienequeasociarunpuertoauna interfacederedyponerloaescucharporconexiones.Finalmente,seaceptanlasconexiondelos clientesusandosocket.accept()enunaiteracininfinitahastaqueelprogramatermineolevanteuna excepcin.Losserversusanlamismainterfacesocketquelosclientes. host='' port=9876 #Creaciondelobjetosockets=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Definirlasopcionesdelsocket s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #Asociarloaunpuerto+interface s.bind(host,port) #Ponerloaescucharporconexioness.listen(3)

Comunicandoconsockets Pythonprovee2manerasparaenviardataatravsdelared:objetosdesocket,yobjetostipofichero usandosocket.makefile(). Losobjetosdesocketseusancuandohayunanecesidaddecontrolareltamao,lostiempode espera,ualgunotrodetalledeladataqueestasiendoescritaoleida. Losobjetosdeficherosonmejoressisetrabajaconprotocolosorientadosaconexinyaquepueden manejarelanlisissintcticodeladatarecibidaquehasidogarantizadaporelprotocolo. Erroresenlatransmisinpuedenocurrirporvariosfactorestalescomo,ladesconexindeun servidor,errordedireccionamiento,etc.Porellopythondefine4posiblesexcepciones: socket.errorparaproblemasgeneralesdeentrada/salida socket.gaierrorparaerrordebsquedadeinformacindedireccionamiento. socket.herrorparaerroresdedireccionamientoparafuncionesqueusanh_errnoenC. socket.timeoutparamanejartiempodeesperadespusdehaberllamadosettimeout()sobreun socket. Loserroresconlosobjetostipoficherosenrealidadhacenunallamadaalsocketdelsistema,asique seaplicanlosmismoserroresquelosobjetosdesocket.Tambinsedebeevitarelbloqueomutuo entreelemisoryelreceptor,porellohayqueasegurarenvio/recibodedataconsocket.shutdown() antesderecibir/enviarnuevadata. Sobretiemposdeesperaparadetectarymanejarerroresesutilizandotimeouts,conestosepuede conseguirquepythondetecteinactividadenelsistemacuandohaycomunicacinentreelclientey elservidor.Parahabilitartimeouts,llamamosasocket.settimeout()enviandoeltiempolimiteen segundos,luegosiexisteunproblemadetiempodeesperasellamarsocket.timeoutcomo excepcin. Tambinsepuedenrealizartransmisionesdeunsolosentidousandollamadasasocket.shutdown(), conestologramossocketsdeunasolavia(halfopensockets).Estoestilsiserequiereasegurar quetodaladataescritahasidotransmitida,opreveerdeadlocksenunacomunicacin.Alfinalizar elllamadoashutdownyasegurarquetodaladatahasidotransmitidaenesavia,elsocketnopodr serusadonuevamente. Lallamadaasocket.shutdown()requiereunargumentoparaindicarelmododefuncionamientoo mododebloqueo. 0previenelecturas 1previeneescrituras 2previenelecturasyescrituras

CODIGODEEJEMPLO: Elsiguienteejemploloherealizadoorientadoaconexinysinconexin,enamboselservidor recibecomoparmetrounficherodelarbol*nixparaserlistadoyenviadoalcliente;paraejecutar elficheroseranecesario2consolasabiertasoelservidorcorriendoen2doplano. #./[script][fichero] #./serverTCP.py #./clienteTCP.py/etc/ Clientesconpython ClienteTCP #!/usr/bin/python #Clienteobjetosocket importsocket,sys host="127.0.0.1" port=10101 filename=sys.argv[1] #Creaciondelobjetosocket(IPv4,TCP) try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) exceptsocket.error,e: print"Errorcreandoelsocket:%s"%e #Conectandolohaciaunhostremoto try: s.connect((host,port)) exceptsocket.gaierror,e: print"Errorconectandoalservidor%s"%e try: s.sendall(filename) exceptsocket.error,e: print"Errorenviandodatos:%s"%e while1: try: buf=s.recv(2048) exceptsocket.error,e: print"Errorreciviendodatos:%s"%e ifnotlen(buf): break sys.stdout.write(buf) ClienteUDP #!/usr/bin/python importsocket,sys host="127.0.0.1" port=10101 message=sys.argv[1] try: s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) exceptsocket.error,e:

print"Errorcreandoelsocket:%s:"%e try: s.sendto(message,(host,port)) exceptsocket.error,e: print"Errorenviandodatos:%s"%e s.settimeout(5) while1: try: message,address=s.recvfrom(2048) exceptsocket.timeout: print"Cerradoporinactividad" sys.exit(1) exceptsocket.error,e: print"Errorrecibiendodatos:%s"%e ifnotlen(message): break sys.stdout.write(message+"\n")

Serversconpython ServerTCP #!/usr/bin/python importsocket,pickle,os host="" port=10101 #Creaciondelobjetosocket(IPv4,TCP) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Definirlasopcionesdelsocket s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #Asociarloaunpuerto+interface s.bind((host,port)) #Ponerloaescucharporconexiones s.listen(3) print"Corriendosobrepuerto%d;CtrlCparainterrumpir"%port while1: try: csock,caddr=s.accept() exceptKeyboadInterrupt: raise except: traceback.print_exc() continue #Manejandolaconexion try: print"Clienteconectado",csock.getpeername() exceptKeyboadInterrupt: raise except:

traceback.print_exc() while1: try: data=csock.recv(2048) ifnotlen(data): break dir=os.listdir(data) fordirindir: csock.sendall(dir+"\n") csock.shutdown(1) exceptKeyboadInterrupt: raise except: traceback.print_exc() csock.close()

ServerUDP #!/usr/bin/python #ServerUDP.py importsocket,os host="" port=10101 s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) s.bind((host,port)) print"Corriendosobrepuerto%d;CtrlCparainterrumpir"%port while1: try: message,address=s.recvfrom(2048) print"Gotdatafrom",address dir=os.listdir(message) forlistdirindir: s.sendto(listdir,address) exceptKeyboardInterrupt: raise except: traceback.print_exc()