2017-12-09 1 views
0

UDP 통신을 시작했습니다. 단순한 스트라이프 다운 버전에서 클라이언트는 기본적으로 이렇게합니다. (예, 많은 if 및 error 검사가 코드에 있으며 No, 많은 정의가 없으면 작동하지 않습니다.) 여기에 실제로 코드보다 conseptual)UDP 및 소켓이 클라이언트에 응답 중입니다.

sock = socket(AF_INET, SOCK_DGRAM, 0); 
server_length = sizeof(struct sockaddr_in); 
sendto(sock, "Hi", 3, 0, (struct sockaddr *)&myaddr, server_length); 
numRes = recvfrom(sock, (char *)buff, (int)sizeof(buff), 0, (struct sockaddr *)&myaddr, &server_length); 

그리고 서버는 기본적으로 동일 :

sock=socket(AF_INET, SOCK_DGRAM, 0); 
bind(sock,(struct sockaddr *)&server,length); 
resBytes=recvfrom(sock,buff,(int)sizeof(buff),0,(struct sockaddr *)&from, &fromlen); 
sendto(sock, "Test",5, 0, (struct sockaddr *)&from, fromlen); 

이 작동합니다. 양쪽 끝은 상대방이 보내는 데이터를받습니다.

내 문제는 다음과 같습니다. 서버가 많은 요청을 동시에 처리해야합니다. 다른 스레드에서 클라이언트에 다시 보내기 전에 다른 스레드에서 처리 할 수 ​​있도록 메시지 대기열을 만들었습니다. 이 작업을 수행 할 때 보내는 소켓을 새로 만들었으며 메시지 뒤에 나오는 동일한 "보낸 사람"주소를 사용했지만 클라이언트는 메시지를받지 못했습니다.

UDP 메시지에 대한 회신이 동일한 소켓으로 수행되어야한다는 점을 이해해야합니까?

동일한 소켓을 보내고 받는데 3 개의 클라이언트가 메시지를 보내는 경우 어떻게됩니까? 처리 된 후 임의의 순서로 응답합니다. 이게 효과가 있니?

나는 클라이언트에서 "서버"를 만들 수 있지만, 내 생각에 모든 NAT가 그 아이디어를 빠르게 죽일 것입니다.

은 내가 시도하려고하는 것은 더하거나 덜 :

sock=socket(AF_INET, SOCK_DGRAM, 0); 
sock2=socket(AF_INET, SOCK_DGRAM, 0); 

bind(sock,(struct sockaddr *)&server,length); 
resBytes=recvfrom(sock,buff,(int)sizeof(buff),0,(struct sockaddr *)&from, &fromlen); 

sendto(sock2, "Test",5, 0, (struct sockaddr *)&from, fromlen); 

이런 종류의 코드가 작동해야하는 경우 이러한 경우가처럼, 내 디버깅로 돌아갈 것입니다,하지만 지금은 것입니다.

편집 : 누군가가 "멀티 스레딩"을 태그로 추가했습니다. 멀티 쓰레드를 잊어 버려. 같은 요청에 대해 즉각적으로 응답하지 않는 이유를 설명하면된다. 그게 필요한 경우 하나의 스레드에서 모든 의사 소통을 할 수 있습니다. 미안하지만 사람들을 혼란스럽게하지만, 여기에서 나의 주요 질문은 : a) 클라이언트에서 "서버"를 정의하지 않고 다른 socked로 응답을 보낼 수 있습니까? b) 그렇지 않다면 동일한 socked (IE 클라이언트 A 전송, 클라이언트 B 전송, 클라이언트 B 응답, 클라이언트 A 응답, 클라이언트 A 응답)에서 임의의 응답 순서를 처리하는 방법

+0

소켓은 여러 스레드가 공유 할 수 없습니다. 하지만 UDP는 비 연결형 프로토콜이므로 다른 소켓을 사용하여 보내고받을 수 있습니다. – user0042

+0

@ user0042 : "소켓을 여러 스레드에서 공유 할 수 없습니다. *"물론 가능합니다. 액세스가 동기화되는 방식에 불과합니다. – alk

+0

@alk 음, 동기화는 개별 스레드를 약간 사용하는 목적을 무효로합니다. – user0042

답변

1

단일 UDP 소켓이 소켓이 연결되어 있지 않으면 여러 소스에서 데이터를 수신하고 여러 피어에 데이터를 전송할 수 있습니다. 즉, 명시 적으로 또는 암시 적으로 소켓을 바인딩 한 다음 sendtorecvfrom (또는 recv)을 사용하면 동일한 소켓을 사용하여 여러 피어에서 데이터를 보내고받을 수 있습니다. 그러나 먼저 소켓이 connect이라면 연결된 ip : 포트, 즉 일반적으로 데이터를받은 동일한 소켓에 바인딩 된 소켓에서만 데이터를 수신 할 수 있습니다.

이것을 테스트하려면 단순히 파이썬 서버를 사용할 수 있습니다 (C와 동일하게 작동합니다). 이 서버는 두 개의 소켓, 즉 sock1sock2을 생성합니다. 그것은 sock1에 메시지를 수신 한 후 처음 sock2합니다 (원본 메시지를받지 않은 한) 다음 sock1 (원본 메시지를받은 하나)를 사용하여 메시지를 다시 보내드립니다 : 피어으로

from socket import * 

sock1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) 
sock2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) 

sock1.bind(('127.0.0.1',9999)) 
data,addr = sock1.recvfrom(1024) 
print("got '{}' from {}".format(data,addr)) 

sock2.sendto(b"send from sock2", addr) 
sock1.sendto(b"send from sock1", addr) 

을 우리는 구성에 따라 연결된 소켓을 사용하는 클라이언트를 가지고 있습니다 (즉,connect + send) 또는 접속되어 있지 않은 소켓 (즉, 더 connectsendto) :

from socket import * 

connected=False 
sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP) 
if connected: 
    sock.connect(('127.0.0.1',9999)) 
    sock.send('send from connected client') 
else: 
    sock.sendto('send from unconnected client',('127.0.0.1',9999)) 
while True: 
    data,addr = sock.recvfrom(1024) 
    print("got '{}' from {}".format(data,addr)) 

당신이 연결된 소켓 (connected=True) 당신이 위로 sock1에서 메시지를 받게됩니다 것을 볼 수 있습니다와 클라이언트를 실행하는 경우,하지 01,233,028,565,591,885,489 (클라이언트가 접속되어 있지 않은 소켓을 사용하는 대신 경우

got 'send from sock1' from ('127.0.0.1', 9999) 

: 클라이언트가 연결되어 있고 sock2이 (암묵적으로) 다른 주소에 바인딩 포트 : sock1이기 때문에 (명시 적)이 IP에 바인딩3210)는이 sock1sock2에서 모두 메시지가 나타납니다

got 'send from sock2' from ('127.0.0.1', 44596) 
got 'send from sock1' from ('127.0.0.1', 9999) 
+0

고마워요. 이것은 내 질문에 답하고있다. 내가 볼 수있는 한, 나는 "연결되지 않았다"는 것을 두개의 소켓에서 돌려 보낸다. 그럼 내 코드에 문제가있을거야. –

+0

@AslakBerby : 클라이언트와 서버간에 NAT를 수행하는 장치가있는 경우 일반적으로 연결의 양쪽에서 ip, port로 구성된 a * 상태 *를 만들고이 상태와 일치하는 서버에서만 패킷을 전달합니다. 이 특정 예에서는 sock1에서 보낸 패킷이 NAT 장치를 통과하는 반면 sock2에서 보낸 패킷은 일치하는 상태가 없으므로 버려집니다. NAT를 수행하지 않더라도 스테이트 풀 방화벽의 경우에도 마찬가지입니다. –

+0

나는 그것을 깨닫기 시작했다. 오늘날 대부분의 가정에서는 인터넷과 NAT간에 일종의 NAT가 있으므로 NAT와 함께 작동하는지 확인한 다음 연결된 버전으로 이동해야합니다. 모든 UDP 코드를 동일한 클래스로 옮기고 하나의 소켓 만 사용했습니다. 여러 클라이언트와 연결할 수 있는지 확인하기 위해 몇 가지 테스트를 수행해야합니다. –

관련 문제