Python 에서는 기본적으로 Socket Library 를 제공해준다. 그리고 async i/o 모듈인 medusa 가 이제는 기본으로 제공된다.
1.1. Client ¶
~cpp
from socket import *
host = "localhost"
port = 9000
addr = (host, port)
sock = socket(AF_INET, SOCK_STREAM)
sock.connect(addr)
sock.send("TEST")
sock.close
1.2. Server ¶
~cpp
from socket import *
port = 9010
bufsize = 1024
maximumConnection = 5
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost",port))
sock.listen(maximumConnection)
while 1:
newsock, client_addr = sock.accept()
print "Client connected:",client_addr
data = newsock.recv(bufsize)
print data
2. UDP Socket ¶
~cpp
#server.py
from socket import *
host = "localhost"
port = 1005
buf = 1024
addr = (host, port)
UDPSock = socket(AF_INET, SOCK_DGRAM)
UDPSock.bind(addr)
while 1:
data, addr = UDPSock.recvfrom(buf)
if not data:
print "Client has exited!"
break
else:
print "\n Received message '", data,"'"
UDPSock.close()
#client.py
from socket import *
host = "localhost"
port = 1005
buf = 1024
addr = (host, port)
UDPSock = socket(AF_INET, SOCK_DGRAM)
def_msg = "==Enter message to send to server=="
print "\n", def_msg
while(1):
data = raw_input('>> ')
if not data:
break
else:
if(UDPSock.sendto(data,addr)):
print "Sending message '",data,"'..."
UDPSock.close()
3. normal socket ¶
역시. 아주아주 간단한 예제.~
또는, 기본 모듈로 있는 SocketServer 모듈을 사용할 수 있다. 다음은 간단한 예제.
~cpp
from socket import *
from threading import *
class ListenThread(Thread):
def __init__(self, aServer):
Thread.__init__(self)
self.server=aServer
def run(self):
clientConnection, address = self.server.listenSock.accept()
print address
clientConnection.send("hahaharn")
clientConnection.close()
self.server.listenSock.close()
class Server:
def serve(self, aPort):
self.listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
here=('',aPort)
self.listenSock.bind(here)
self.listenSock.listen(5)
listenThread=ListenThread(self)
listenThread.start()
if __name__=="__main__":
server = Server()
server.serve(30002)
~cpp
from SocketServer import *
HOST = ('', 7000)
ClientList = []
ClientConnections = []
class MyServer (BaseRequestHandler):
def broadcast (self, msg):
for conn in ClientConnections:
conn.send (msg)
def handle(self):
conn = self.request
if conn:
peername = conn.getpeername ()
ClientList.append (peername)
ClientConnections.append (conn)
print "Requested by ", peername
try:
cmd = raw_input (">> ")
while cmd:
if cmd == 'ls':
print "== Connected Client Lists =="
print ClientList
self.broadcast ("ls command inputed...n")
cmd = raw_input (">> ")
except:
print "Socket Error occured.."
return
if __name__ == '__main__':
my_server = ThreadingTCPServer (HOST, MyServer)
my_server.serve_forever ()
4. Medusa ¶
Medusa 는 내부적으로 select / poll 를 이용, 비동기 소켓부분을 구현한다. 소켓 이벤트들 처리에 대한 인터페이스가 아주 깔끔. 참 마음에 든다.
MFC 의 CSocket 를 사용하는 스타일로 프로그래밍을 할 수 있는데, Python 이기에 코드가 더 깔끔. 그리고 Windows/Linux 양쪽 다 가능.
다음은 화일 보내는 부분과 관련한 간단한 예제.
다음은 화일 받는 부분과 관련한 간단한 예제.
여기서 recv 메소드는 데이터가 들어온 만큼 받는다. (즉, 버퍼사이즈만큼 데이터가 들어올때까지 기다리지 않는다.)
~cpp
import asyncore
import socket
from threading import *
import os
import os.path
class FileSendChannel(asyncore.dispatcher, Thread):
def __init__(self, aConnection, anAddress):
asyncore.dispatcher.__init__(self, aConnection)
Thread.__init__(self)
print "file send channel create."
print "address :", anAddress
self.address = anAddress
def run(self):
print "file send channel start."
self.fileSendMain()
def writable(self):
return not self.connected
def handle_read(self):
bufferSize=8192
data = self.recv(bufferSize)
print "data :", data
def handle_close(self):
self.close()
print "closed channel..."
def getFileSize(self, aFileName):
return os.path.getsize(aFileName)
def fileSendMain(self):
aFileName='f:/sample.jpg'
fileSize=self.getFileSize(aFileName)
print "file size : ", fileSize
f = open(aFileName, "rb")
print "file opened.."
currentReaded=0
while currentReaded < fileSize:
data = f.read(1024)
#currentReaded = f.tell()
sended = self.send(data)
currentReaded+=sended
f.seek(currentReaded, 0)
print "current : %d, sended : %d"%(currentReaded, sended)
f.close()
print "send completed..."
self.close()
class FileSendServer(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
def initialize(self):
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
def handle_accept(self):
connection, address = self.accept()
channel = FileSendChannel(connection, address)
channel.start()
def handle_close(self):
pass
def handle_read(self):
pass
def handle_write(self):
pass
def serve(self, aPort):
self.initialize()
here = ('', aPort)
self.bind(here)
self.listen(5)
if __name__=='__main__':
server = FileSendServer()
server.serve(30002)
asyncore.loop()
~cpp
import asyncore
import socket
class FileReceiveChannel(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.received = 0
self.f=open("f://output1.jpg","wb")
def handle_connect(self):
print "connected..."
def writable(self):
return not self.connected
def handle_write(self):
pass
def handle_read(self):
data = self.recv(8192)
self.received += len(data)
print "received : %d, %d"%(len(data), self.received)
self.f.write(data)
def handle_close(self):
print "closed..."
self.f.close()
self.close()
def main(self, aHost, aPort):
self.connect((aHost, aPort))
if __name__=="__main__":
client=FileReceiveChannel()
host = "localhost"
port = 30002
client.main(host, port)
asyncore.loop()









