WeJr 5 Denunciar post Postado Novembro 27, 2013 Estou criando um programa que deve se comunicar através de broadcast já que não haverá um servidor definido. Tentei criar uma classe para a conexão, mas só consegui resultados com TCP. Em Python consegui consegui fazer. Aprendi o básico da linguagem e através de alguns tutoriais criei a classe para a conexão, mas por enquanto quero fazer em C++. Fazendo o mesmo que o script Python meu código em C++ parece enviar e receber algo, mas ele só recebe em uma segunda instância do programa e mesmo assim não exibe nada. Funciona somente se o endereço de broadcast for de uma interface especifica (192.168.2.255). Não sei porque isso acontece, mas a interface é do VMWare. Código C++: #pragma once #include "stdafx.h" #include <winsock2.h> #include <ws2tcpip.h> #pragma comment (lib, "Ws2_32.lib") #define DEFAULT_PORT "6881" #define MAX_PACKET_SIZE 1000000 SOCKET NetworkSocket; int _tmain(int argc, _TCHAR* argv[]) { //Criar socket UDP { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); NetworkSocket = INVALID_SOCKET; NetworkSocket = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(NetworkSocket, SOL_SOCKET, SO_REUSEADDR, (char*)1, sizeof((char*)1)); setsockopt(NetworkSocket, SOL_SOCKET, SO_BROADCAST, (char*)1, sizeof((char*)1)); struct addrinfo* result = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; getaddrinfo("", DEFAULT_PORT, &hints, &result); bind(NetworkSocket, result->ai_addr, (int)result->ai_addrlen); // } addrinfo broadcast { result = NULL; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; getaddrinfo("255.255.255.255", DEFAULT_PORT, &hints, &result); // } Enviar { char* data = "Ola"; sendto(NetworkSocket, data, sizeof(data), 0, result->ai_addr, (int)result->ai_addrlen); printf("Send: |%s|\n", data); // } Receber { char network_data[MAX_PACKET_SIZE]; recv(NetworkSocket, network_data, MAX_PACKET_SIZE, 0); printf("Receive: |%s|\n", network_data); // } while(true){ } return 0; } Código Python: import socket class Network: DEFAULT_PORT = 6881 _MAX_PACKET_SIZE = 1000000 def __init__(self): self.NetworkSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.NetworkSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.NetworkSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.NetworkSocket.bind(('',self.DEFAULT_PORT)) def send(self, data, address = False, ip = False): if address == False: if ip == False: address = ('<broadcast>', self.DEFAULT_PORT) else: address = (ip, self.DEFAULT_PORT) self.NetworkSocket.sendto(data, address) return True def recv(self): return self.NetworkSocket.recvfrom(self._MAX_PACKET_SIZE) Para realizar alguns testes da classe em Python criei o main para receber alguns argumentos e realizar as operações: from network import Network import sys import getopt def main(argv): try: opts, args = getopt.getopt(argv,"hrs",["help","receive","send","times=","string=","ipaddress="]) except getopt.GetoptError: print('test.py (-r [--times=<TIMES>] | -s --string=<STRING> [--ipaddress=<IPADDRESS>])') sys.exit(2) times = None str = None IPaddr = None if ('-h', '') in opts or ('--help','') in opts: print('test.py (-r [--times=<TIMES>] | -s --string=<STRING> [--ipaddress=<IPADDRESS>])') elif ('-r', '') in opts or ('--receive','') in opts: Net = Network() for opt, arg in opts: if opt == '--times': times = arg if times != None: if times == 'ever': while True: message, address = Net.recv() print("Message:", message.decode(), "Address:", address[0]) else: times = int(times) while times != 0: message, address = Net.recv() print("Message:", message.decode(), "Address:", address[0]) times -= 1 else: message, address = Net.recv() print("Message:", message.decode(), "Address:", address[0]) elif ('-s', '') in opts or ('--send','') in opts: for opt, arg in opts: if opt == '--string': str = arg elif opt == '--ipaddress': IPaddr = arg if str != None: if IPaddr != None: Net = Network() Net.send(bytes(str,"UTF-8"),ip=IPaddr) else: Net = Network() Net.send(bytes(str,"UTF-8")) else: print('test.py (-r [--times=<TIMES>] | -s --string=<STRING> [--ipaddress=<IPADDRESS>])') else: print('test.py (-r [--times=<TIMES>] | -s --string=<STRING> [--ipaddress=<IPADDRESS>])') sys.exit() if __name__ == "__main__": main(sys.argv[1:]) Compartilhar este post Link para o post Compartilhar em outros sites
GBecker 51 Denunciar post Postado Novembro 29, 2013 tentou colocar um analisador de protocolo tipo Wireshark para ver a comunicação? Compartilhar este post Link para o post Compartilhar em outros sites
WeJr 5 Denunciar post Postado Novembro 30, 2013 Sim. Com o programa em C++, consigo somente observar alguma comunicação se o endereço de broadcast for 192.168.2.255, mas em Python está funcionando para todos. Agora desativei as interfaces de rede, com exceção de uma, e tentei novamente. Em C++ só funcionou com o endereço de broadcast da interface que ficou ativa. Acho que o programa em C++ está enviando somente se o endereço de broadcast for o da interface ativa com maior prioridade ou algo assim. Compartilhar este post Link para o post Compartilhar em outros sites
GBecker 51 Denunciar post Postado Novembro 30, 2013 Os dois utilizam a mesma biblioteca de sockets do windows. Pesquisou na documentação MDSN se tem alguma configuração pra fazer? http://msdn.microsoft.com/pt-br/library/aa916134.aspx Compartilhar este post Link para o post Compartilhar em outros sites
WeJr 5 Denunciar post Postado Novembro 30, 2013 Já pesquisei muito nesta documentação, mas achei poucas respostas. Parece que por algum motivo o broadcast para 255.255.255.255 não funciona em C++. Dessa forma eu teria que criar um socket para cada rede em que o computador estiver conectado e teria que executar cada operação de envio ou recebimento em todos, se tornando algo complicado. Se o endereço da rede na qual o socket está associado for 192.168.1.1 o endereço broadcast para envio deve ser o dessa rede, como, por exemplo, 192.168.1.255. Não funciona enviar para 255.255.255.255 ou receber de todas interfaces. Código C++: (só fiz algumas mudanças na forma como o endereço é configurado) #pragma once #include "stdafx.h" #include <winsock2.h> #include <ws2tcpip.h> #pragma comment (lib, "Ws2_32.lib") #define DEFAULT_PORT 6881 #define MAX_PACKET_SIZE 1000000 SOCKET NetworkSocket; int _tmain(int argc, _TCHAR* argv[]) { //Criar socket UDP { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); NetworkSocket = INVALID_SOCKET; NetworkSocket = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(NetworkSocket, SOL_SOCKET, SO_REUSEADDR, (char*)1, sizeof((char*)1)); setsockopt(NetworkSocket, SOL_SOCKET, SO_BROADCAST, (char*)1, sizeof((char*)1)); struct sockaddr_in localAddr; ZeroMemory(&localAddr, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_port = htons(DEFAULT_PORT); localAddr.sin_addr.s_addr = inet_addr("192.168.1.1"); bind(NetworkSocket, (sockaddr*)&localAddr, sizeof(localAddr)); // } sockaddr_in broadcast { struct sockaddr_in broadcastAddr; ZeroMemory(&broadcastAddr, sizeof(broadcastAddr)); broadcastAddr.sin_family = AF_INET; broadcastAddr.sin_port = htons(DEFAULT_PORT); broadcastAddr.sin_addr.s_addr = inet_addr("192.168.1.255"); // } Enviar { char* data = "Ola"; sendto(NetworkSocket, data, sizeof(data), 0, (sockaddr*)&broadcastAddr, sizeof(broadcastAddr)); printf("Send: |%s|\n", data); // } Receber { char network_data[MAX_PACKET_SIZE]; recv(NetworkSocket, network_data, MAX_PACKET_SIZE, 0); printf("Receive: |%s|\n", network_data); // } while(true){ } return 0; } Compartilhar este post Link para o post Compartilhar em outros sites
WeJr 5 Denunciar post Postado Dezembro 1, 2013 Achei um pequeno erro que impedia o envio de broadcast para 255.255.255.255, mas mesmo assim a mensagem só vai para uma rede. Stack Overflow - UDP-Broadcast on all interfaces: http://stackoverflow.com/questions/683624/udp-broadcast-on-all-interfaces Se eu quiser enviar para todas as redes terei mesmo que enviar separadamente para cada uma delas. Solução: Vou estudar multicast para ver se pode resolver meu problema, se não, vou implementar o envio por broadcast para cada uma das redes em que o computador estiver conectado. Erros no código: setsockopt(NetworkSocket, SOL_SOCKET, SO_REUSEADDR, (char*)1, sizeof((char*)1)); setsockopt(NetworkSocket, SOL_SOCKET, SO_BROADCAST, (char*)1, sizeof((char*)1)); O certo é assim: int yes = 1; setsockopt(NetworkSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); setsockopt(NetworkSocket, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); Código C++ com a correção: #pragma once #include "stdafx.h" #include <winsock2.h> #include <ws2tcpip.h> #pragma comment (lib, "Ws2_32.lib") #define DEFAULT_PORT 6881 #define MAX_PACKET_SIZE 1000000 SOCKET NetworkSocket; int _tmain(int argc, _TCHAR* argv[]) { //Criar socket UDP { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); NetworkSocket = INVALID_SOCKET; NetworkSocket = socket(AF_INET, SOCK_DGRAM, 0); int yes = 1; setsockopt(NetworkSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); setsockopt(NetworkSocket, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); struct sockaddr_in localAddr; ZeroMemory(&localAddr, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_port = htons(DEFAULT_PORT); localAddr.sin_addr.s_addr = INADDR_ANY; bind(NetworkSocket, (sockaddr*)&localAddr, sizeof(localAddr)); // } sockaddr_in broadcast { struct sockaddr_in broadcastAddr; ZeroMemory(&broadcastAddr, sizeof(broadcastAddr)); broadcastAddr.sin_family = AF_INET; broadcastAddr.sin_port = htons(DEFAULT_PORT); broadcastAddr.sin_addr.s_addr = INADDR_BROADCAST; // } Enviar { char* data = "Ola"; sendto(NetworkSocket, data, sizeof(data), 0, (sockaddr*)&broadcastAddr, sizeof(broadcastAddr)); printf("Send: |%s|\n", data); // } Receber { char network_data[MAX_PACKET_SIZE]; recv(NetworkSocket, network_data, MAX_PACKET_SIZE, 0); printf("Receive: |%s|\n", network_data); // } while(true){ } return 0; } Compartilhar este post Link para o post Compartilhar em outros sites