int main() { HANDLE hFile; hFile = CreateFile(SlotName, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile failed with %d.\n", GetLastError()); return FALSE; } WriteSlot(hFile, TEXT("Message one for mailslot.")); WriteSlot(hFile, TEXT("Message two for mailslot.")); Sleep(5000); WriteSlot(hFile, TEXT("Message three for mailslot.")); CloseHandle(hFile); return TRUE; }
// Função relativa à thread do servidor TCP. é o intermédio entre o client OPC e o client TCP, // trocando assim mensagens constantemente entre ambos os clientes. DWORD WINAPI TCPServer(LPVOID id) { WSADATA wsaData; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL; struct addrinfo hints; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; int seqdados = 0; char ack_string[13]; char ack_data[14]; char msgreq[TAMMSGREQ+1]; char msgsp[TAMMSGSP+1]; Monitor<vector<int>> mSocket(VERB_ON); char dados2[55]; char dados1[100]; LPTSTR MailSlotDados = TEXT("\\\\.\\mailslot\\mailslotDados"); //Inicializa mailslot Dados (caminho da troca de dados de processo) LPTSTR MailSlotSP = TEXT("\\\\.\\mailslot\\mailslotSP"); //Inicializa mailslot SP (caminho da troca de setpoints) HANDLE hSlotDados = CreateMailslot(MailSlotDados, //Criação do mailslot de dados //Código adaptado do MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365785%28v=vs.85%29.aspx 0, // no maximum message size MAILSLOT_WAIT_FOREVER, // no time-out for operations (LPSECURITY_ATTRIBUTES) NULL); // default security if (hSlotDados == INVALID_HANDLE_VALUE) { printf("CreateMailslot failed with %d\n", GetLastError()); return FALSE; } else printf("MailslotDados created successfully.\n"); HANDLE hFileSP = CreateFile(MailSlotSP, // Abertura de arquivo para leitura do mailslot de setpoints // Código adaptado do MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365802%28v=vs.85%29.aspx GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hFileSP == INVALID_HANDLE_VALUE) printf("CreateFile failed with %d.\n", GetLastError()); else printf("MailSlotSP File criado.\n"); // Criação de um evento para sincronizar a leitura do mailslot de setpoints. // Este evento será setado após os setpoints serem escritos no arquivo, // desta forma, o client OPC apenas vai ler deste quando tal ocorrer. HANDLE hMSWrite = CreateEvent(NULL, FALSE, FALSE, TEXT("hMSWrite")); if (hMSWrite == INVALID_HANDLE_VALUE) printf("Handle hMSWrite failed with %d.\n", GetLastError()); else printf("hMSWrite, handle criado.\n"); // Daqui em diante, grande parte do código de inicialização de um servidor TCP foi retirado do MSDN // https://msdn.microsoft.com/pt-br/library/windows/desktop/ms737593%28v=vs.85%29.aspx // A partir do código acima, alterações foram feitas para que a comunicação também com o Cliente OPC ocorresse // e também para que reconexões possam ser feitas. O servidor continua a tratar apenas um cliente simultâneo, // visto que não era previsto múltiplos acessos pela especificação do trabalho prático (apenas um computador do processo) // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed with error: %d\n", iResult); return 1; } printf("TCP Server inicializado.\n");//Linha adicionada ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { printf("getaddrinfo failed with error: %d\n", iResult); WSACleanup(); return 1; } printf("Endereco resolvido.\n");//Linha adicionada // Create a SOCKET for connecting to server ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("socket failed with error: %ld\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } printf("Socket TCP criado.\n");//Linha adicionada // Setup the TCP listening socket iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("bind failed with error: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } printf("Socket TCP de escuta inicializado.\n");//Linha adicionada freeaddrinfo(result); while(1){ // Este While permite que após uma conexão ser finalizada, o servidor volte a // escutar por uma nova conexão. iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("listen failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } printf("Socket TCP ouvindo.\n");//Linha adicionada // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); printf("Cliente conectado.\n"); //Linha adicionada if (ClientSocket == INVALID_SOCKET) { printf("accept failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // Daqui para baixo grande parte do código foi alterado, // visando a comunicação bilateral com TCP Cliente e OPC Cliente do { // Receber pedido de dados iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); // Testa se uma mensagem chegou if (iResult > 0) { // Analise da mensagem. Requisicao de pacotes? if (iResult == TAMMSGREQ){ strncpy_s(msgreq, sizeof(msgreq), recvbuf, iResult); // Confirmacao de requisicao. Testa tag inicial if (strncmp(msgreq, "100000", 6) == 0){ printf("Requisicao de pacotes recebida!\nMsg recebida: %s\nBytes recebidos: %d\n", msgreq, iResult); // Caso a mensagem recebida for uma requisicao de pacotes, aguarda que estes sejam enviados pelo cliente OPC // e os repassa ao cliente TCP ReadSlot(hSlotDados,recvbuf); // Monta a mensagem com os dados mais uma tag identificadora e uma contagem sequencial sprintf_s(dados1,"200000|%.6d|%s",seqdados,recvbuf); // Envia dados em resposta ao pedido memcpy_s(&dados2, 55, dados1, 55); iSendResult = send( ClientSocket, dados2, 55, 0 ); // Incrementa sequenciador seqdados++; // Teste do envio if (iSendResult == SOCKET_ERROR) { printf("send failed with error: %d\n", WSAGetLastError()); iResult = 0; } } // Tag inicial desconhecida else { printf("Mensagem nao identificada recebida.\nMsg recebida: %s\nBytes recebidos: %d\n", msgreq, iResult); iResult = 0; } } //IF result = request // Analise da mensagem. Envio de set points? else if (iResult == TAMMSGSP){ strncpy_s(msgsp, sizeof(msgsp), recvbuf, iResult); // Confirmacao da chegada de set points. Testa tag inicial if (strncmp(msgsp, "300000", 6) == 0){ printf("Set-points recebidos!\nMsg recebida: %s\nBytes recebidos: %d\n", msgsp, iResult); // Caso a mensagem recebida for um envio de setpoints, repassa-os ao cliente OPC e sinaliza o envio WriteSlot(hFileSP,msgsp); SetEvent(hMSWrite); // Monta uma nova mensagem e envia um ACK de confirmação ao cliente TCP sprintf_s(ack_data,"%s|%c%c%c%c%c%c",ACKDATA,recvbuf[7],recvbuf[8],recvbuf[9],recvbuf[10],recvbuf[11],recvbuf[12]); memcpy_s(&ack_string, 13, ack_data, 13); iSendResult = send(ClientSocket,ack_string,TAMMSGACK,0); // Teste do envio if (iSendResult == SOCKET_ERROR) { printf("send failed with error: %d\n", WSAGetLastError()); iResult = 0; } } // Tag inicial desconhecida else { printf("Mensagem nao identificada recebida.\nMsg recebida: %s\nBytes recebidos: %d\n", msgreq, iResult); iResult = 0; } } //IF result = sp } //IF result > 0 else if (iResult == 0) printf("Connection closing...\n"); else { printf("recv failed with error: %d\n", WSAGetLastError()); iResult = 0; } } while (iResult > 0); cout << "Aguardando reconexao..." << endl; } // No longer need server socket closesocket(ListenSocket); //Inicialização sockets // shutdown the connection since we're done iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed with error: %d\n", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } // cleanup CloseHandle(hMSWrite); CloseHandle(hSlotDados); CloseHandle(hFileSP); closesocket(ClientSocket); WSACleanup(); return(0); }