Komunikacja sieciowa z biblioteki DLL

0

Hej,
Na wstępie: C++ znam tylko trochę. Do tej pory bardziej PHP, więc muszę się przestawić - potrzebuję dorobić do biblioteki DLL kod, który pozwoli na wystawienie portu zewnętrznego (w sieci lokalnej) i komunikację po tym porcie.
Biblioteka wspomniana to plugin do X-Plane 11, jeśli kogoś interesuje.
Wyglądałoby to tak, że X-Plane ładuje bibliotekę, która wystawia na zewnątrz jakąś funkcjonalność, a ja ją później obrabiam w innym miejscu.
Czy to w ogóle możliwe? Jeśli tak, to czy możecie mi zaproponować jakieś tutoriale? Korzystam z Visual Studio 2017 Community i wolałbym nie zmieniać środowiska, bo musiałbym wszystko przekonfigurować i znowu dostosowywać...

0

Ale ty bardziej potrzebujesz chyba klienta tcp, żeby po wczytaniu ddl i pozyskaniu danych wysłał je do tej zew apki.
Jak duże paczki danych to będą? Czy oczekujesz jakiegoś wyniku zwrotnego który będzie wpływał na tą gre?

1

Hm, próbuję zrozumieć co chcesz zrobić, podzielmy to na punkty

  1. Bierzesz cudzą bibliotekę która jest pluginem do X-Plane 11
  2. Dodajesz do biblioteki swój kod zamieniający ją w serwer TCP (nie wiem czy to poprawne okreslenie), ale tak żeby dalej była pluginem do X-Plane 11
  3. Komunikujesz się swoim programem z tym serwerem po TCP

Czy dobrze Cię rozumiem?

0

To ma być plugin do X-Plane, a nie nakładka na inny plugin. Odczytywanie danych w teorii mam, ale nie mam jak tego podpiąć, bo rozwiązania, które teraz zastosowałem, blokują wykonanie aplikacji dopóki nie otrzyma ona pakietów z aplikacji testowej.
Paczki będą małe (około 1-2 KB). Nie chcę robić tego tak, że apka na androida, która docelowo ma odczytywać te dane, miałaby być serwerem - to nie przejdzie. Jedyny wpływ na grę ma być akceptowalnym opóźnieniem pobrania danych i wysłania paczki - nic innego ten plugin nie będzie robił.
Na chwilę obecną próbuję skleić coś z winsock2, ale brak umiejętności podpięcia pod to wielowątkowości mnie blokuje.

0

Kolega wyżej wrzucił link do TCPListenera, ale z C#. Poszukałem na necie czegoś podobnego i znalazłem coś: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1TcpListener.php ale to nie rozwiązuje chyba problemu z tym, że połączenie będzie blokowało wykonanie instrukcji w bibliotece...

1

Albo tylko na początku nawiązujesz połączenie i je podtrzymujesz przez całe życie apki wysyłając przez nie dane. Albo przy każdym wysyłaniu bierzesz i odpalasz wątek w którym to już sobie nawiązuje połączenie i wysyła te dane nie blokując apki.

0

http://www.cplusplus.com/reference/thread/thread/detach/
Zrobiłem jak w powyższym przykładzie - walnąłem zammiast 'join' - 'detach' i zadziałało :D
Tylko pytanie: czy przy wychodzeniu z pluginu powinienem jakoś zwalniać zasoby z winsock2?

0

Oto kod wątku, który obsługuje wystawienie danych:

void InstrumentDataThread() {
	useSocket = true;
	WSADATA wsaData;
	SOCKET mainSocket;
	sockaddr_in service;
	int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (result != NO_ERROR) {
		useSocket = false;
	}
	else {
		mainSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (mainSocket == INVALID_SOCKET)
		{
			useSocket = false;
			WSACleanup();
		}
		else {
			memset(&service, 0, sizeof(service));
			service.sin_family = AF_INET;
			service.sin_addr.s_addr = inet_addr("127.0.0.1");
			service.sin_port = htons(30123);
			if (bind(mainSocket, (SOCKADDR *)& service, sizeof(service)) == SOCKET_ERROR)
			{
				useSocket = false;
				closesocket(mainSocket);
			}
			else {
				if (listen(mainSocket, 1) == SOCKET_ERROR) {
					useSocket = false;
				}
				else {
					SOCKET acceptSocket = SOCKET_ERROR;

					acceptSocket = accept(mainSocket, NULL, NULL);
					if (acceptSocket != SOCKET_ERROR) {
						mainSocket = acceptSocket;

						char Buffer[256];
						while (useSocket) {
							sprintf(Buffer, "%f", psi);

							int bytesSent;
							int bytesRecv = SOCKET_ERROR;
							char recvbuf[2] = "";

							bytesSent = send(mainSocket, Buffer, strlen(Buffer), 0);

							while (bytesRecv == SOCKET_ERROR)
							{
								bytesRecv = recv(mainSocket, recvbuf, 1, 0);

								if (bytesRecv == 0 || bytesRecv == WSAECONNRESET)
								{
									useSocket = false;
									break;
								}

								if (bytesRecv < 0) {
									useSocket = false;
									break;
								}
							}
						}

						closesocket(mainSocket);
					}
				}
			}
		}
	}
	WSACleanup();

	InstrumentDataThread();
}

Na chwilę obecną nie podtrzymuje połączenia.
Na końcu jest powtórne wywołanie funkcji, ale problem jest taki, że po połączeniu klienta i zakończeniu połączenia, aplikacja się wywala :/
Jak mogę zrestartować wątek tak, aby mógł się do niego podłączyć inny klient?

W funkcji głównej modułu uruchamiam pierwszy wątek tak:

	std::thread t(InstrumentDataThread);
	t.detach();

1 użytkowników online, w tym zalogowanych: 0, gości: 1