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

02.09.2013, 20:59

Winsock recv

Hey Leute

Habe eben mal schnell eine Winsock anwendung geschrieben, um auszuprobieren wie das mit den warteschlangen ist.


Mein problem:

Bei recv werden in der for schleife beide clients überprüft auf einen Sendestatus, nur wenn beide gesendet haben, wird es angezeigt.


Hier mal der Source vom Server

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//Netzwerkprogrammierung Winsock api Socket
//TCP SERVER
#include<cstdio>
#include<iostream>
#include<WinSock2.h>
#include<Windows.h>
using namespace std;
char recbuf[256];

char sendbuf[256];
int main()
{
    //Hilfsvariable
    long res;

    //Versionsdaten
    WSAData wsData;

    //ws2_32.dll aktivieren
    res=WSAStartup(MAKEWORD(2,0),&wsData);
    if(res==0)
    {
        cout<<"WSSTARTUP SUCESSFULL "<< endl;

    }
    else
    {
        cout <<"ERROR WSSTARTUP   " << WSAGetLastError()<<endl;
    }
    //Socket Deskriptoren
    SOCKET slisten, client[2];

    //Socket anfordern b.z.w Kommunikation einrichten
    slisten = socket(AF_INET, SOCK_STREAM, 0);
        if(slisten != INVALID_SOCKET)
    {
        cout<<"SOCKET SUCESSFULL" << endl;

    }
    else
    {
        cout <<"ERROR SOCKET   " << WSAGetLastError()<<endl;
    }

    //Verbindungsinformationen
    sockaddr_in info; // sockaddr
    info.sin_addr.s_addr = inet_addr("127.0.0.1");
    info.sin_family = AF_INET;
    info.sin_port = htons(54345);
    int infolen = sizeof(info);
    res = bind(slisten, (struct sockaddr*)&info,infolen);
    if(res != SOCKET_ERROR)
    {
        cout<<"Bind SUCESSFULL" << endl;

    }
    else
    {
        cout <<"Bind SOCKET   " << WSAGetLastError()<<endl;
    }
    //Warteschlange für einkommende verbindungen
    res = listen(slisten,SOMAXCONN);
    if(res != SOCKET_ERROR)
    {
        cout<<"listen SUCESSFULL "<< endl;

    }
    else
    {
        cout <<"list error  " << WSAGetLastError()<<endl;
    }
    sockaddr_in clientinfo;
    int clientinfolen = sizeof(clientinfo);
    bool ten;
    int ClientAd=0;
    ten=true;





        int counti=0;
    while(ten==true)
    {

        if(ClientAd<=1)
        {
            cout <<ClientAd<< endl;
            client[ClientAd] = accept(slisten, (struct sockaddr*)&clientinfo, &clientinfolen);

          ClientAd++;
                  cout <<ClientAd<< endl;
        if(client[ClientAd] != SOCKET_ERROR)
        {
            cout <<"Client Accepted: " <<inet_ntoa(clientinfo.sin_addr) << ": "
            << ntohs(clientinfo.sin_port) << endl;



        }
        }


        if(res==SOCKET_ERROR)
        {
            cout << "ERROR SEND()" << endl;
        }


        for(int i=0; i<ClientAd; i++)
        {
                  res = recv(client[i], recbuf,256,0);
        if(res==SOCKET_ERROR)
      {
          cout << "Client Disconnected" << endl;
          ten=false;

      }
      else
      {

          cout << res << "Bytes Recieved" << endl;
        cout << recbuf << endl;


      }
      memset(&recbuf,0,sizeof(recbuf));
        }

    }
    closesocket(slisten);
    closesocket(client[0]);
    closesocket(client[1]);
    WSACleanup();
    return 0;

}



Gruß Leri :)

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

02.09.2013, 22:48

Solange ich es nicht überlesen habe, stellst du deinen Socket nicht auf non-blocking um.
Das wäre eine Möglichkeit dein Problem zu lösen. Hier mehr Infos dazu: http://www.win32developer.com/tutorial/w…tutorial_3.shtm

Im wesentlichen musst du den ioctl Aufruf machen und du musst darauf achten, dass recv nun mit WSAEWOULDBLOCK als Fehler zurückkehren kann.

Ach ja, und dein Server wird durch diese Änderung erstmal einen CPU Kern vollständig belegen, obwohl die meiste Zeit nichts zu tun ist. Eine einfache, wenn auch nicht unbedingt perfekte Lösung wäre natürlich ein kurzer Sleep nach jedem Durchlauf.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

3

02.09.2013, 23:46

Das was er wirklich sucht ist select
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

03.09.2013, 00:13

Oder Threads, wäre wohl eine gute Gelegenheit, sich damit zu beschäftigen... ;)

rnlf

Frischling

Beiträge: 85

Beruf: Softwareingenieur Raumfahrt

  • Private Nachricht senden

5

03.09.2013, 12:07

Oder asio...

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

6

03.09.2013, 18:16

Auch Möglichkeiten, aber da darf der Threadersteller mehr oder weniger seine Sachen neu schreiben und sich neu reindenken.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Faule Socke

Community-Fossil

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

7

04.09.2013, 19:06

Er kann Threads oder select verwenden. Ich würde jedoch von Threads abraten, immer nur eine Sache gleichzeitig lernen. Sonst vermischt er Probleme möglicherweise. Bei Threads muss er sich ja gleich mit dem ganzen Sync. Zeug befassen, rausfinden, welche Operationen auf Sockets atomic sind, etc. Nonblocking Sockets sind etwas gewöhnungsbedürftig. Will man nur in Spezialfällen, z.B. bei Green Threads o.ä.

Ein kleiner Netzwerkserver mit Threads könnte so aussehen: Pro Socket einen Thread. Dieser macht ein blocking select auf read und write des Sockets. Je nach Fall werden dann entweder Daten geschrieben (dazu muss eine Queue in die ein Master-Thread schreibt gelockt werden) oder gelesen.

Threads haben allerdings auch den Nachteil eines großen Overheads was Erstellung und Verwaltung betrifft. Unter Python hat man sehr einfache Möglichkeiten, green Threads zu erstellen und zu benutzen, ohne dass man sich groß um Sync-Probleme, Deadlocks oder ähnliches kümmern müsste.

Gruß Socke

8

06.09.2013, 19:53

Also ich denke ich verwende wirklich Threads, auch wenn es vielleicht schwierig werden sollte.

Habe mir das Buch Der C++ Programmierer zugelegt, wo auch Threads b.z.w die boost/thread behandelt werden.

Habe jetzt nen Ansatz wie ich das mache, und passt auch zu Sockes Beitrag, ich nehme für jeden Socket ein eigenen Thread.

Für den Server gibt es dann eine Rec und Send funktion, die einen Socket erwartet und das array von allen Sockets, um an alle die Nachricht zu schicken.
Die Clients bekommen 1 thread für das Senden von Nachrichten, das auch während des schreibens Nachrichten gesendet werden können.

Denke das der Thread bei den Clients nicht unbedingt notwendig wäre, aber zur Sicherheit ^^ werde ich dafür auch noch einen Separaten anlegen.

Gruß Leri :)

Werbeanzeige