Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

30.01.2011, 17:28

Multithreading und Winsock

Hi
ich habe mal angefangen einen kleinen Chat auf der Basis von Winsock zu entwickeln. Ich wollte das Senden und Empfangen über zwei verschiedene Threads laufen lassen aber der debugger spuckt mir immerwieder einen Laufzeitfehler aus wenn ich etwas schreibe und das dann versende ?(
Hier noch der relevante Code

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
HRESULT CCreateServer::CreateServer()
{
    ...
    while(go == true)
    {
        hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadSend(), 0, 0, 0);
        hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadGet(), 0, 0, 0);

        WaitForSingleObject(hThread1, INFINITE);
        WaitForSingleObject(hThread2, INFINITE);
    }

    CloseHandle(hThread1);
    CloseHandle(hThread2);

    return 0;
}

long WINAPI CCreateServer::ThreadSend()
{
    CChat chat;
    std::cout << "Server: ";
    std::cin.getline(buf,sizeof(buf));
    send(connectedSocket,buf,256,0);
    sended = true;
    if(buf[0] == '*' && buf[1] == '*' && buf[2] == '*')
    {
        go = false;
    }
    if(buf[0] == '*' && buf[1] == 'h' && buf[2] == 'm' && buf[3] == '*')
    {
        go = false;
        system("cls");
        closesocket(connectedSocket);
        WSACleanup();
        chat.ShowMainMenu();
    }

    return 0;
}
long WINAPI CCreateServer::ThreadGet()
{
    recv(connectedSocket,buf,256,0);
    std::cout << "Client: " << buf << std::endl;

    return 0;
}

Ich steh grad völlig aufm Sclauf. Hoffe ihr könnt mir weiterhelfen.

mfg Fabian
Metal ist keine Musik sondern eine Religion.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

2

30.01.2011, 17:51

Zunächsteinmal bin ich erstaunt, dass er das überhaupt kompiliert (was darauf hindeutet, dass du entweder globale oder statische Variablen nutzt).
Hast du denn auch rausgefunden an welcher Stelle der Laufzeitfehler auftritt und um welchen Laufzeitfehler es sich handelt?
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

idontknow

unregistriert

3

30.01.2011, 18:19

C-/C++-Quelltext

1
2
hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadSend(), 0, 0, 0);
hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadGet(), 0, 0, 0);


I lol'd.

Außerdem sollte man _beginthreadex verwenden anstelle von CreateThread. Und was du da machst ist nunmal schlichtweg falsch^^
Du kannst natürlich eine Methode in eine Funktion casten, aber was dabei herauskommt ist schlichtweg fail, ub, Laufzeitfehler^^

4

30.01.2011, 18:28

C-/C++-Quelltext

1
2
_beginthreadex(NULL, 0,(unsigned int(_stdcall*)(void*))ThreadSend(), 0, 0, 0);
_beginthreadex(NULL, 0,(unsigned int(_stdcall*)(void*))ThreadGet(), 0, 0, 0);

So geht das auch nicht :/ ich glaub ich hab da was falsch verstanden^^
Metal ist keine Musik sondern eine Religion.

idontknow

unregistriert

5

30.01.2011, 18:31

OMG

Gerade rumprobiert und deinen Fehler gefunden, der mir (peinlich, aber ich gebe es zu!) am Anfang nicht sofort aufgefallen it...

C-/C++-Quelltext

1
_beginthreadex(NULL, 0,(unsigned int(_stdcall*)(void*))ThreadSend(), 0, 0, 0);


1. _beginthreadex macht im Prinzip das selbe wie CreateThread, wenns also mit letzterem nicht funktioniert funktionierts mit ersterem auch nicht!
2. Warum ThreadSend()?

Weißt du was dein Programm macht? Es ruft die Method ThreadSend auf, welche eine Zahl vom Typ "long" zurückgibt und diese Zahl wird dann in eine Funktion gecastet.
Programmiertechnischer SuperGAU, kA in welche Fehlerkategorie man das steckt, aber auf jedenfall ganz weit oben. Du scheinst dich noch nicht wirklich miT Threads auseinandergesetzt zu haben^^

edit: Meine Thread Klasse, ganz simpel und auch nicht top, aber sollte ausreichen + besser als das was du da fabrizierst :P.

Header:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#pragma once

#include <Windows.h>

template <class T>
class ThreadDelegate : public ThreadEntryPoint
{
public:
    typedef void (T::*ThreadProc)();

    ThreadDelegate(T &obj, ThreadProc proc)
        : m_Object(obj), m_Proc(proc)
    {
    }

    void Run()
    {
        (m_Object.*m_Proc)();
    };

private:
    T &m_Object;
    ThreadProc m_Proc;
};

struct ThreadEntryPoint
{
    virtual void Run() = 0;
};


class Thread
{
public:

    Thread(ThreadEntryPoint *entry);
    ~Thread();  

private:
    static unsigned int __stdcall EntryPoint(void* userdata);
    HANDLE m_ThreadHandle;
};


CPP:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "Thread.h"

#include <process.h>
#include <memory>

Thread::Thread(ThreadEntryPoint *entry)
{
    m_ThreadHandle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &Thread::EntryPoint, entry, 0, NULL));
}

Thread::~Thread()
{
    if(m_ThreadHandle)
        CloseHandle(m_ThreadHandle);
}

unsigned int __stdcall Thread::EntryPoint(void* userdata)
{
    ThreadEntryPoint* entry = reinterpret_cast<ThreadEntryPoint*>(userdata);
    entry->Run();
    return 0;
}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

30.01.2011, 19:06

Notiz am Rande:
Es gibt kein "sended", sondern nur "sent".
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

7

30.01.2011, 19:30

kA in welche Fehlerkategorie man das steckt

Stock, der einem von C++ zwischen die Beine geworfen wird. ;)

8

30.01.2011, 21:14

Gut das geht jetzt. Aber

C-/C++-Quelltext

1
2
3
4
while(go == true)
{
    Send = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,send,(LPVOID)1,0,&dwthread));
}

kann ich ja trotzdem nicht stehen lassen weil dann ja immer ein neuer Thread erzeugt wird :/
Wie kann ich das jetzt ohne whileschleife lösen?
Metal ist keine Musik sondern eine Religion.

idontknow

unregistriert

9

30.01.2011, 21:22

Wenn "send" keine Funktion ist wirds nicht funktionieren! Außerdem musst du einfach für den Void-Ptr Null übergeben, wenn du ihn nicht benutzt, aber sicher nicht 1 -.-
Und ja nonstops Threads spammen ist nicht gut da hast du recht.
Dein Code hat aber noch ganz andere probleme^^

10

30.01.2011, 21:25

Den Code den ich oben gepostet habe ist jetzt fast zu 100 % raus (alles bis auf die While schleife)
send ist übrigens eine Funktion

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
unsigned int WINAPI send(VOID* data)
{
    CChat chat;
    CCreateServer serv;

    std::cout << "Server: ";
    std::cin.getline(serv.GetBuf(),sizeof(serv.GetBuf()));
    send(serv.getServerSocket(),serv.GetBuf(),256,0);
    
    if(serv.GetBuf()[0] == '*' && serv.GetBuf()[1] == '*' && serv.GetBuf()[2] == '*')
    {
        serv.go = false;
    }
    if(serv.GetBuf()[0] == '*' && serv.GetBuf()[1] == 'h' && serv.GetBuf()[2] == 'm' && serv.GetBuf()[3] == '*')
    {
        serv.go = false;
        system("cls");
        closesocket(serv.getServerSocket());
        WSACleanup();
        chat.ShowMainMenu();
    }

    return 0;
}

Aber ich weiß nicht wie ich das lösen soll das der Thread praktisch "immer" und nicht nur einmal ausgeführt wird.
Metal ist keine Musik sondern eine Religion.

Werbeanzeige