Avatar billede mad_man Nybegynder
25. juli 2003 - 12:45 Der er 21 kommentarer og
1 løsning

sende tilbage til alle clineter

jaa.. nu har jeg fået lavet mig en server der sender til bage til den client der sendte det... hvordan får man så den til at sende til alle clienter (til chat ala IRC)
håber i kan hjælpe...
og hvordan sender man tekst med mellemrum
og hvordan tømmer man en "char recvbuf[256];"
/mad_man

kode kommer lige om 2 sec
Avatar billede mad_man Nybegynder
25. juli 2003 - 12:47 #1
#include <winsock.h>
#include <iostream>

#define MAXCONN 10

using namespace std;
const int kBufferSize = 1024;

DWORD WINAPI Echo(void* sock_)
{
    SOCKET sock = (SOCKET)sock_;
   
    char acReadBuffer[kBufferSize];
    int nReadBytes;
    do {
        nReadBytes = recv(sock, acReadBuffer, kBufferSize, 0);
        if (nReadBytes > 0) {
            cout << "Received " << nReadBytes <<
                    " bytes from client." << endl;
       
            int nSentBytes = 0;
            while (nSentBytes < nReadBytes) {
                int nTemp = send(sock, acReadBuffer + nSentBytes,
                        nReadBytes - nSentBytes, 0);
                if (nTemp > 0) {
                    cout << "Sent " << nTemp <<
                            " bytes back to client." << endl;
                    nSentBytes += nTemp;
                }
                else if (nTemp == SOCKET_ERROR) {
                    return false;
                }
                else {
                    cout << "Peer unexpectedly dropped connection!" << endl;
                    return true;
                }
            }
        }
        else if (nReadBytes == SOCKET_ERROR) {
            return false;
        }
    } while (nReadBytes != 0);

    cout << "Connection closed by peer." << endl;
    return true;
}

void accptconn(SOCKET lytter)
{
    sockaddr_in sinRemote;
    int nAddrSize = sizeof(sinRemote);

    while (1) {
        SOCKET sock = accept(lytter, (sockaddr*)&sinRemote,
                &nAddrSize);
        if (sock != INVALID_SOCKET)
        {
            cout << "Accepted connection from " <<
                    inet_ntoa(sinRemote.sin_addr) << ":" <<
                    ntohs(sinRemote.sin_port) << "." <<
                    endl;

            DWORD nThreadID;
            CreateThread(0, 0, Echo,(void*)sock, 0, &nThreadID);
        }
    }
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow)
{
    WORD sockVersion;
    WSADATA wsaData;
    int sock;

    sockVersion = MAKEWORD(1, 1);//    WORD (1, 1);
   
    WSAStartup(sockVersion, &wsaData);
   
    SOCKET lytter;
    lytter = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   
    if(lytter == INVALID_SOCKET)
    {
        WSACleanup();
        return 0;
    }
    SOCKADDR_IN srvinf;
    srvinf.sin_family = AF_INET;
    srvinf.sin_addr.s_addr = INADDR_ANY;
    srvinf.sin_port = htons(8888);
   
    sock = bind(lytter, (LPSOCKADDR)&srvinf, sizeof(struct sockaddr));
   
    if(sock == SOCKET_ERROR)
    {
        WSACleanup();
        return 0;
    }
   
    sock = listen(lytter, MAXCONN);
    if(sock == SOCKET_ERROR)
    {
        WSACleanup();
        return 0;
    }
    accptconn(lytter);
   
   
}
Avatar billede repsak Nybegynder
25. juli 2003 - 12:48 #2
Du opsamler alle dine klienter i en liste (dvs. når en klient connecterblir den adderet i en liste). Så laver du bare en for-loop som skriver til klienterne i listen
Avatar billede mad_man Nybegynder
25. juli 2003 - 12:49 #3
hov glømte og sige er lidt ny til det her c++ værk... så der må gerne komme en lille linje kode eller 2 som exempel tak =)
Avatar billede arne_v Ekspert
25. juli 2003 - 12:56 #4
Hvis du skal sende til alle klienter er du nød til at sende til hver
klient socket.

Der burde ikk evære nogen som helst problemer med at sende tekster med
mellemrumn i (man sender med en adresse og en længde - og de data sendes
uanset mellemrum nul bytes og andet).

strcpy(recvbuf,"");

sætter recvbuf til en tom streng.
Avatar billede repsak Nybegynder
25. juli 2003 - 12:58 #5
noget ala
for (int count = 0; count < array->GetSize() ; count++){
  Klient * klient = (Klient*)array->GetAt(i);
  klient->SendMessage("Hejsa");
}

hvor Klient er den klasse som repræsenterer din klient og array er en tabel/liste med alle forbundne klienter
Avatar billede mad_man Nybegynder
25. juli 2003 - 13:07 #6
char exit[] = "exit";
        char buffer[256];
        ZeroMemory(buffer, 256);

            do   
        {   
          cout << "skriv noget:";
          cin >> buffer;
          nret = send(theSocket,buffer,strlen(buffer),0); //strlen(buffer)
          }while( strcmp(exit,buffer) !=0);

skulle det der ik du til og sende med mellemrum ????
Avatar billede mad_man Nybegynder
25. juli 2003 - 13:10 #7
hvis du nu kikker i det kode jeg allerrede har skrevet.. kan det bruges til og sende til alle klienter og hvordan...
Avatar billede arne_v Ekspert
25. juli 2003 - 13:10 #8
Det er udmærket til at sende mellemrum med ud over socket.

*MEN*

cin >> buffer

læser kun det første ord in !
Avatar billede mad_man Nybegynder
25. juli 2003 - 13:11 #9
hvordan får jeg den sA til at læse alle ord ind ???
Avatar billede arne_v Ekspert
25. juli 2003 - 13:12 #10
Hvis du vil have en hel linie, så brug:
  cin.getline
metoden.
Avatar billede arne_v Ekspert
25. juli 2003 - 13:14 #11
Avatar billede arne_v Ekspert
25. juli 2003 - 13:17 #12
repsaks løsning er en high-level OO løsning bruger en avanceret data struktur
til at have listen.

Din kode er tæt på ren C (du bruger cin/cout, // og erklæring midt
i koden fra C++).

Det er ligesom 2 forskellige måder at gribe det an på.
Avatar billede arne_v Ekspert
25. juli 2003 - 13:21 #13
Hvis du skal lave noget tilsvarende, så skal det vær enoget i stil med:

SOCKET sock[100];
int nsock;

void accptconn(SOCKET lytter)
{
    sockaddr_in sinRemote;
    int nAddrSize = sizeof(sinRemote);
    nsock=0;
    while (1) {
        sock[nsock] = accept(lytter, (sockaddr*)&sinRemote,
                &nAddrSize);
        if (sock[nsock] != INVALID_SOCKET)
        {
            cout << "Accepted connection from " <<
                    inet_ntoa(sinRemote.sin_addr) << ":" <<
                    ntohs(sinRemote.sin_port) << "." <<
                    endl;

            DWORD nThreadID;
            CreateThread(0, 0, Echo,(void*)sock[nsock], 0, &nThreadID);
            nsock++;
        }
    }
}

og så kan du lave en for løkke fra 0 til nsock og bruge sock.
Avatar billede mad_man Nybegynder
25. juli 2003 - 13:38 #14
nu kommer der en fejl når jeg prøver at kompile.. den kommer i:
SOCKET sock[nsock] = accept(lytter, (sockaddr*)&sinRemote,&nAddrSize);

57 C:\Documents and Settings\Mad_Man\Skrivebord\Chat prog\main.cpp
variable-sized object `sock' may not be initialized
Avatar billede mad_man Nybegynder
25. juli 2003 - 14:14 #15
det er i ,&nAddrSize fejlen ligger men hvad fejler den ???
Avatar billede mad_man Nybegynder
25. juli 2003 - 14:25 #16
hvad gør SOCKET sock[100]; linjen ---- og hvorfor tallet 100
Avatar billede arne_v Ekspert
25. juli 2003 - 14:34 #17
sock[nsock] =

ikke

SOCKET sock[nsock] =

fordi jeg har flyttet erklæringen op som global variabel, så andre
funktione rkan bruge den.
Avatar billede arne_v Ekspert
25. juli 2003 - 14:35 #18
SOCKET sock[100];

sætter plads af til 100 SOCKET's og kan dermed klare 100 clients.
Avatar billede mad_man Nybegynder
25. juli 2003 - 15:48 #19
er jeg kørt helt i skoven ???
DWORD WINAPI Echo(void* sock_)
{
    SOCKET sock = (SOCKET)sock_;
   
    char acReadBuffer[kBufferSize];
    int nReadBytes;
    while(1) {
        nReadBytes = recv(sock, acReadBuffer, kBufferSize, 0);
       
        if (nReadBytes > 0) {
            cout << "Received " << nReadBytes <<
                    " bytes from client." << endl;
            for (int count = 0; count < nsock ; count++){
                        int nSentBytes = 0;
                        while (nSentBytes < nReadBytes) {
                                                int nTemp = send(sock, acReadBuffer + nSentBytes,nReadBytes - nSentBytes, 0);
                                                if (nTemp > 0) {
                                                    cout << "Sent " << nTemp << " bytes back to client." << endl;
                                                    nSentBytes += nTemp;
                                                }
                                                    else if (nTemp == SOCKET_ERROR) {
                                                    return false;
                                                }
                                                else {
                                                    cout << "Peer unexpectedly dropped connection!" << endl;
                                                    return true;
                                                }
                        }
            }
        }
        else if (nReadBytes == SOCKET_ERROR) {
            return false;
        }
    } while (nReadBytes != 0);

    cout << "Connection closed by peer." << endl;
    return true;
}

det sender bare 2 echos tilbage hvis der er 2 clienter på.. men det sender ik til den anden client:(
Avatar billede arne_v Ekspert
25. juli 2003 - 16:04 #20
Du "skygger" for den globale variabel.
Avatar billede arne_v Ekspert
25. juli 2003 - 16:06 #21
Altså skal du lavet noget a la (bare copy paste og rettet i browser):

DWORD WINAPI Echo(void* sock_)
{
    SOCKET thissock = (SOCKET)sock_;
 
    char acReadBuffer[kBufferSize];
    int nReadBytes;
    while(1) {
        nReadBytes = recv(thissock, acReadBuffer, kBufferSize, 0);
     
        if (nReadBytes > 0) {
            cout << "Received " << nReadBytes <<
                    " bytes from client." << endl;
            for (int count = 0; count < nsock ; count++){
                        int nSentBytes = 0;
                        while (nSentBytes < nReadBytes) {
                                                int nTemp = send(sock[count], acReadBuffer + nSentBytes,nReadBytes - nSentBytes, 0);
                                                if (nTemp > 0) {
                                                    cout << "Sent " << nTemp << " bytes back to client." << endl;
                                                    nSentBytes += nTemp;
                                                }
                                                    else if (nTemp == SOCKET_ERROR) {
                                                    return false;
                                                }
                                                else {
                                                    cout << "Peer unexpectedly dropped connection!" << endl;
                                                    return true;
                                                }
                        }
            }
        }
        else if (nReadBytes == SOCKET_ERROR) {
            return false;
        }
    } while (nReadBytes != 0);

    cout << "Connection closed by peer." << endl;
    return true;
}
Avatar billede mad_man Nybegynder
25. juli 2003 - 16:09 #22
ahhh
jeg takker 1000 gange for hjælpen...
nu funker det som det skal... jeg har også lært en del ved det her =)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester