2012-12-09 5 views
3

저는 네트워크 프로그래밍이 어떻게 더 잘 이루어지고 있는지를 이해하기 위해 파이썬 소켓을 골머리 앓고 있습니다. 지금은 서버에 연결하는 클라이언트를 설정하려고 시도하고 있으며 종료하기 전에 여러 개의 메시지를 보낼 수 있습니다. 나는 아직도 모든 것을 이해하지 못하고 오직 하나의 메시지를 보내기 만 할 수 있습니다. 아마도 소켓 프로그래밍에 익숙한 사람에게는 명백한 일일 것입니다. 다른 사람이 여러 개의 메시지를 보내는 방법을 설명해 주시겠습니까? 연결, 바인딩, 닫기, recv 및 모든 주 소켓 기능이 어떻게 작동하는지 설명하는 좋은 소스를 제공 할 수 있습니까? (대부분의 소스는 그냥 사용시기 말해 찾을 수 있습니다.)Python 소켓 - 서버는 한 번만 수신합니까?

클라이언트

# !usr/bin/python 

import socket 
import sys 


def main(): 
    host = "" 
    port = 8934 
    message = "Hello World!" 

    host = raw_input("Enter IP: ") 
    #Create Socket 
    try: 
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    except socket.error, msg: 
     print "Failed to create socket. Error code: %s Error Message: %s"%(str(msg[0]),msg[1]) 
     sys.exit() 
    print "Socket created" 

    #Connect to server 
    s.connect((host,port)) 

    while message != "/e": 
     #Send Data 
     message = raw_input("Send >> ") 
     try: 
      s.sendall(message) 
     except socket.error, msg: 
      print "ERROR %s"%(msg[1]) 
      print "Failed to send." 
     s.close() 

if __name__ == "__main__": 
    main() 

서버가 클라이언트 측에서

# !usr/bin/python 

import socket 
import sys 

HOST = "" 
PORT = 8934 
s = socket.socket() 

class BoServer: 


    def __init__(self): 
     try: 
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     except socket.error,msg: 
      print "Unable to create socket" 
      sys.exit() 
     print "Socket created." 
    def bind(self): 
     s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     try: 
      s.bind((HOST,PORT)) 
     except socket.error,msg: 
      print "Bind failed. Closing..." 
      sys.exit() 
     print "Socket bound." 
    def run(self): 
     while True: 
      s.listen(10) 
      print "Socket Listening" 
      conn, addr = s.accept() 
      print "Connected to %s:%s"%(addr[0],addr[1]) 
      income = conn.recv(4096) 
      if income != "": 
       print income 

def main(): 
    serv = BoServer() 
    serv.bind() 
    serv.run() 

if __name__ == "__main__": 
    main() 
+2

한 번만 '듣기'및 '수락'하고 'conn.recv' 만 반복하면됩니다. – jozzas

+0

새 소켓에서 한 번만 읽은 소켓을 승인 한 후 서버가 소켓을 닫습니다. –

+0

한가지 명심해야 할 점은이 문제를 해결 한 후에도 각'recv'에 정확하게'send' 하나의 결과를 얻는 것에 의존 할 수 없다는 것입니다. 로컬에서 테스트 할 때 99.999 %의 시간이 걸릴 것으로 보이지만 인터넷에 배포하자마자 항상 실패합니다. 당신은'send'의 절반,''send''''''2-1/2''를 얻을 수 있습니다. 별도의 메시지가 필요하면 구분 기호 (예 : 개행), 길이/유형/어떤 접두사 (예 : 넷 스트링) 또는 자체 구분 문자 유형 (예 : JSON-RPC)을 사용해야하며,'recv '를 버퍼에 넣고 파싱합니다. – abarnert

답변

6

, 당신은 소켓을 닫는 것 while True: 루프 내부에 있으므로 루프의 향후 반복에서 더 많은 메시지를 전송할 수 없습니다. 다른 연결에서 각 메시지를 보내려는 경우 루프 내에서 소켓을 만들어야합니다. 동일한 연결에서 여러 개의 메시지를 보내려는 경우에는 루프 외부에서 닫기 호출을 이동해야합니다.

서버 쪽에서 루프의 반복이 불필요한 경우마다 한 번씩 listen()를 실행합니다. 버퍼링 된 수신 연결의 큐 길이를 설정하는 것이므로 한 번만 호출하면됩니다. 또한 들어오는 다른 연결을 수락하는 루프의 두 x 째 반복을 계속하기 전에 소켓에서 단 한 번의 읽기 만 수행합니다.

서버의 작동 방식에 따라 또 다른 잠재적 인 문제는 한 번에 하나의 수신 연결 만 처리한다는 것입니다. 오래 실행중인 연결을 처리하려는 경우 문제가 될 수 있습니다. 여러 개의 연결을 동시에 처리하려면 자체 스레드 (예 : SocketServer standard library moduleThreadingTCPServer 클래스 사용)에서 각 연결을 처리하거나 Twisted과 같은 비동기 IO 프레임 워크를 사용하는 것이 좋습니다.

+0

제임스 감사합니다. 좀 더 잘 이해할 수 있도록 도와주었습니다. – cgasser