문제

UDP 테스트 클라이언트/서버를 작성하고 있으며 방화벽을 통해 가져오고 싶습니다. 아마도 내가해야 할 일은 양측이 올바른 IP와 서버로 전송하는 것입니다. IP를 얻는 것은 문제가되지 않지만 클라이언트가 무작위 무료 포트를 선택하여 사용자에게보고하는 방법은 무엇입니까? 결국 Matchmaker 서버에 연결하기를 원하지만 지금은 간단한 작업 프로토 타입이 필요하며 친구/테스터가 IM을 통해 #을 보내서 테스트 할 수 있도록 포트 번호를 작성하고 싶습니다.

포트 번호는 어떻게 얻습니까? 긴 DESC에 대해 죄송합니다. 나는 사람들이 내가 desc를주지 않을 때 내가 묻는 일을하지 말라고 말한다 :(

도움이 되었습니까?

해결책

To use the highly technical term, this is actually a pretty icky problem or even a pair of icky problems. Depending on the configuration of the firewall, it will usually allow responses from another endpoint on the IP endpoint as the request came from. So... if you friend receives the UDP datagram using something like the recvfrom() system call, the address parameter will receive the IP endpoint information to respond to. So the other end should be able to respond with a sendto() using the same addressing information. Something like:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

The peeraddr on the other side will be your external address or, more correctly, the IP address of your firewall and the port number that it chose to use. The port number that you specify in your code may be completely different than the port that your friend would have to send data to. Ultimately, it might not matter what port you choose to use since the firewall might be sending and receiving on an entirely different port - this is what Network Address Translation is all about. I would recommend reading RFC3235 for some tips on how to overcome that hurdle.

The best approach IMHO is to:

  1. Let the OS choose a port by either calling bind() with a zero port number or skipping the bind altogether
  2. Having the client receive the address information from the socket layer (e.g., the fifth and sixth arguments to recvfrom())
  3. The client sends response to the endpoint retrieved in the previous step
  4. Tweak the firewall configurations until the previous steps work

Of course, all of the magic is in the last step. If you can disable NAT or ensure that the firewall is never going to switch ports, then nailing down a port number and bind-ing to it will work as well. You might want to take a look at %WINDIR%\system32\drivers\etc\services (or /etc/services depending on your OS inclination) to get an idea of what port numbers are reserved or generally in use.

다른 팁

Generally speaking - you - as the developer - choose the port. You can set your application to read the port from a config file or user input - but no magic firewall is going to tell you what port to use...

If I'm understanding your question correctly, I'm not sure there's a way to do what you want programatically (and even if there is, I don't think it's the right approach). I think you need to find a port that isn't in use on the server machine (and perhaps a different or the same port on the client machine, if communication is bi-directional) AND that port must be able to pass through your firewall. I assume since you say "getting an IP is not a problem", you've already configured your firewall to forward some or all ports to a specific computer inside the firewall? If so, the port you seek is one of the ones you forwarded. You can just pick an arbitrary one, as long as no other service is running on that port. Ports below 1024 are reserved, so you probably want to pick a higher number than that. You can use a simple portscanning tool such as nmap to see which services are running on your computer on which ports and pick a different one. Note that nmap can be fooled by firewalls and various bind rules when sockets are created.

I think you're better off picking a fixed port rather than relying on the random port number chosen by the O/S.

If you use a random port you'd have to change your firewall settings each and every time you run the program.

If you're using WINSOCK check this link: http://msdn.microsoft.com/en-us/library/aa280717(VS.60).aspx Basically you have 2 choices set the port to 0 and let the system assign you one or chose a random one try to open the socket if it doesn't work try another (be sure to steer clear of reserved ports)

bind() the socket before you send your data. Specify port 0 to bind(), and the OS will pick an unused port for you. You can then use getsockname() to find out what port wsa chosen.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top