KremTri Δημοσ. 10 Μαΐου 2010 Δημοσ. 10 Μαΐου 2010 Ας μου εξηγησει καποιος ( please ) γιατι κολλάω. Φτιαχνω ενα προγραμματακι client / server και προσπαθω να το κάνω ποληνυματικο. Δεν μπορω να καταλάβω στην ρουτινα του κάθε thread πως θα μπορώ να στέλνω ( υποθετουμε οτι ειμαι απο την πλευρα του server ) και να λαμβάνω δεδομένα. Για κάθε thread πρέπει να φτιάχνω και νέο socket? Με ενα socket δεν μπορω να χρησιμοποιώ πολλά threads? Πως θα πρέπει να χρησιμοποιησω την send και την recv μέσα στη ρουτίνα του thread χωρίς να κολλάει? Εχω μια κλάση serverClass και μια threadClass.Απο εκει και πέρα οι functions τους καλούνται μέσα στη main, εχω τον παρακάτω κώδικα: >#include <stdio.h> #include <winsock.h> #include <stdlib.h> #ifndef serverClassH #define serverClassH class serverClass{ public: serverClass(); ~serverClass(); int createSocket(unsigned short port); bool bindListen(void); bool acceptClient(void); private: WSADATA wsa_data; SOCKET server_sock, client_sock , accept_socket; struct sockaddr_in server_addr, client_addr; }; #pragma hdrstop #include "serverClass.h" #pragma comment(lib,"ws2_32.lib"); serverClass::serverClass(){ if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { exit(1); } } serverClass::~serverClass(){ } int serverClass::createSocket(unsigned short port){ if ((server_sock = socket(PF_INET, SOCK_STREAM,IPPROTO_TCP)) < 0) return false; return server_sock; } bool serverClass::bindListen(void){ memset(&client_addr, 0, sizeof(client_addr)); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(80); if (bind(server_sock, (struct sockaddr *) &server_addr,sizeof(server_addr)) < 0) return false; if (listen(server_sock, SOMAXCONN ) < 0) return false; return true; } bool serverClass::acceptClient(void){ accept_socket = accept( server_sock, NULL, NULL ); if (accept_socket == INVALID_SOCKET) { closesocket(accept_socket); WSACleanup(); return false; } else return true; } και η κλάση για το thread: >//--------------------------------------------------------------------------- #include <stdio.h> #include <winsock.h> #include <stdlib.h> #include <iostream.h> #ifndef threadClassH #define threadClassH struct thread_args { int id; SOCKET server_sock; char *mes; struct sockaddr_in server_addr; }; class threadClass{ public: threadClass(); ~threadClass(); bool allocate_Thread_memory(void); void setParameters(SOCKET server_socket,char* SERVER_ADDRESS); bool createThread(void); private: struct thread_args *starter_thread_arg; HANDLE starter_thread_handle;//for create thead static void* starter_thread(void *args); DWORD starter_thread_id; }; //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- #pragma hdrstop #include "threadClass.h" threadClass::threadClass(){ } threadClass::~threadClass(){ } bool threadClass::allocate_Thread_memory(void){ if((starter_thread_arg = new thread_args)==0) { return false; } return true; } void threadClass::setParameters(SOCKET server_sock,char* SERVER_ADDR){ //set parameters on struct starter_thread_arg->server_sock = server_sock; starter_thread_arg->server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR); starter_thread_arg->mes="HELLO WORLD!!!"; memcpy(&starter_thread_arg->server_addr , &starter_thread_arg->server_addr,sizeof(starter_thread_arg->server_addr)); starter_thread_arg->id = -1; } bool threadClass::createThread(void){ if ((starter_thread_handle = CreateThread(0,0, (LPTHREAD_START_ROUTINE)starter_thread, starter_thread_arg, 0, (LPDWORD)&starter_thread_id)) == 0) return false; cout << endl << "to neo einai:" << starter_thread_arg->id; return true; } void* threadClass::starter_thread(void *args) { struct thread_args *client_thread_arg; //thelei new client_thread_arg client_thread_arg=new thread_args; memcpy(client_thread_arg, args, sizeof(struct thread_args)); client_thread_arg->id= 789; return client_thread_arg; cout << endl <<"is:"<< client_thread_arg->id; cout << endl <<"is:"<< client_thread_arg->server_sock; cout << endl <<"is:" << client_thread_arg->mes; char *buffer="aaaaaa"; if (send(client_thread_arg->server_sock,buffer,strlen(buffer),0) == SOCKET_ERROR){ closesocket(client_thread_arg->server_sock); WSACleanup(); cout << endl << "ERROR SEND"; //return mes; } int a; cout << "pres enter"; cin >> a; int i; char recvbuf[512]; i = recv(client_thread_arg->server_sock, recvbuf , 512 , 0); if(i>0) { recvbuf[i]='\0'; cout << endl << "AAAAAAA OK!!!:" <<recvbuf; // return recvbuf; } else { Sleep(3000); cout << endl << "error occure..."; } /* HANDLE thread_handles[NUM_THREADS]; DWORD thread_ids[NUM_THREADS]; struct thread_args *client_thread_arg; int i; /* for (i = 0; i < NUM_THREADS; i++) { if ((client_thread_arg = (struct thread_args *) malloc(sizeof(struct thread_args))) == 0) fatal_error2("malloc client_thread_arg error"); memcpy(client_thread_arg, args, sizeof(struct thread_args)); client_thread_arg->id = i; if ((thread_handles[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) client_thread, client_thread_arg, 0, (LPDWORD)&thread_ids[i])) == 0) fatal_error2("CreateThread for clients error"); printf("created client thread %d\n", i); fflush(stdout); } free(args); args = 0; printf("%d threads created\n", NUM_THREADS); fflush(stdout); for (i = 0; i < NUM_THREADS; i++) WaitForSingleObject(thread_handles[i], INFINITE); printf("all threads terminated\n"); fflush(stdout); threads_all_done = 1; ExitThread(0); */ } void *client_thread(void *args) { /* struct thread_args *client_thread_arg; struct sockaddr_in server_addr; int server_sock; int client_sock; int on = 1; int bytes_received, bytes_sent; int num_to_read; int total_bytes_received, total_bytes_sent; char buffer[bUFFER_SIZE]; int size; int i; total_bytes_received = total_bytes_sent = 0; client_thread_arg = (struct thread_args *)args; memcpy(&server_addr, &client_thread_arg->server_addr, sizeof(struct sockaddr_in)); server_sock = client_thread_arg->server_sock; if ((client_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) fatal_error("socket() error in client thread"); if (connect(client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) fatal_error("connect() error in client thread"); // wait for the server to send startup message if ((bytes_received = recv(client_sock, buffer, BUFFER_SIZE, 0)) < 0) fatal_error("recv() error in client thread"); if (ioctlsocket(client_sock, FIONBIO, &on) < 0) fatal_error("FIONBIO error in client thread"); size = SEND_SOCK_BUFFER_SIZE; if (setsockopt(client_sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) fatal_error("SO_SNDBUF error in client thread"); size = RECV_SOCK_BUFFER_SIZE; if (setsockopt(client_sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) fatal_error("SO_RCVBUF error in client thread"); for (i = 0; i < CLIENT_LIMIT ; i++) { int errno; if ((bytes_sent = send(client_sock, buffer, BUFFER_SIZE, 0)) != BUFFER_SIZE) { errno = WSAGetLastError(); if (errno == WSAEWOULDBLOCK || errno == WSAENOBUFS) continue; fatal_error("send() error in client thread"); } total_bytes_sent += bytes_sent; num_to_read = 0; if (ioctlsocket(client_sock, FIONREAD, &num_to_read) < 0) fatal_error("FIONREAD error in client thread"); if (num_to_read == 0) continue; if ((bytes_received = recv(client_sock, buffer, num_to_read >= BUFFER_SIZE ? BUFFER_SIZE - 1 : num_to_read, 0)) <= 0) fatal_error("recv() error in client thread"); total_bytes_received += bytes_received; } printf("thread %d total bytes received %d sent %d\n", client_thread_arg->id, total_bytes_received, total_bytes_sent); #if 0 closesocket(client_sock); #endif free(args); */ } //--------------------------------------------------------------------------- #pragma package(smart_init) :cry::cry::cry::cry::cry::cry::cry:
RubiksCube Δημοσ. 10 Μαΐου 2010 Δημοσ. 10 Μαΐου 2010 Η γενική ιδέα είναι: Στο server έχεις ένα listening socket στο οποίο συνδέεται όποιος client θέλει. Από εκεί για κάθε client ξεκινάς ένα νέο thread με νέο socket και από αυτό το νεο socket επικοινωνείς με τον client. Δηλαδή συνολικά έχεις ν+1 threads όπου ν ο αριθμός των συνδεδεμένων clients.
KremTri Δημοσ. 10 Μαΐου 2010 Μέλος Δημοσ. 10 Μαΐου 2010 Αρα θα χρειαστω για καθε client νεο socket και νεο thread!!!! στην ρουτινα ομως του thread πως θα μπορεσω να επικοινωνω με καθε client ξεχωριστα χωρις να κολλάει?????
RubiksCube Δημοσ. 10 Μαΐου 2010 Δημοσ. 10 Μαΐου 2010 Αρα θα χρειαστω για καθε client νεο socket και νεο thread!!!! στην ρουτινα ομως του thread πως θα μπορεσω να επικοινωνω με καθε client ξεχωριστα χωρις να κολλάει????? Κάθε thread θα χειρίζεται έναν μόνο client. Τώρα αυτό το thread θα μπλοκάρει αν χρησιμοποιείς blocking IO (recvfrom()), μέχρι να λάβει δεδομένα από τον συγκεκριμένο client, θα τα επεξεργάζεται και θα ξαναμπλοκάρει (μέσα σε while loop). Αν ψάξεις στο net για έναν πολύ απλό chatserver/client θα πάρεις μια ιδέα πώς ακρβώς λειτουργεί. Σε java τουλάχιστον ο κώδικας είναι πολύ μικρός.
KremTri Δημοσ. 11 Μαΐου 2010 Μέλος Δημοσ. 11 Μαΐου 2010 οκ!!!! εγω χρησιμοποιω την send(...) και την recv(...) που μάλλον ειναι blocking!! ποιες συναρτησεις αντιστοιχα μπορω να χρησιμοποιησω που δεν ειναι blocking????
ntaryl Δημοσ. 11 Μαΐου 2010 Δημοσ. 11 Μαΐου 2010 Eνδιαφερομαι και εγω για το θεμα αλλα οχι για Java. Πιο συγκεκριμενα θελω να καταλαβω τον κωδικα . Μπορει καποιος να αναρτησει κωδικα σε java αφου δεν εχω τον απαραιτητο compiler για να το μελετησω . Ευχαριστω πολυ P.s Εκτος και αν υπαρχει καποιος απλος compiler ετσι ωστε να μπορεσω να μελετησω τον κωδικα .Χωρις να χριεαστει να εγκαταστησω το Netbean
pinball_elf Δημοσ. 12 Μαΐου 2010 Δημοσ. 12 Μαΐου 2010 Ο παρακάτω κώδικας έιναι ένα παράδειγμα ενός πολυνηματικού server σε C για Windows όπως το περιγράφει ο RubiksCube: > #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <winsock2.h> #include <string.h> DWORD WINAPI MyThreadFunction( LPVOID lpParam ); int main (vold) { SOCKET s, con; struct sockaddr_in addr; // the address structure for a TCP socket size_t addr_size; DWORD dwThreadId; HANDLE hThread; int threadCount = 0; // Must be done at the beginning of every WinSock program WSADATA w; // used to store information about WinSock version int error = WSAStartup (0x0202, &w); // Fill in w if (error) { // there was an error return -1; } else fprintf(stdout, "Winsock v%d.%d initialized\n", LOBYTE(w.wVersion), HIBYTE(w.wVersion)); if (w.wVersion != 0x0202) { // wrong WinSock version! WSACleanup (); // unload ws2_32.dll return -1; } s = socket (AF_INET, SOCK_STREAM, 0); // Create socket addr.sin_family = AF_INET; // Address family Internet addr.sin_port = htons (5555); // Assign port 5555 to this socket addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination addr_size = sizeof(addr); if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) { // error WSACleanup (); // unload WinSock return -1; // quit } if (listen(s, 5) == SOCKET_ERROR) /* 5 = max length of the queue of pending connections */ { // error! unable to listen WSACleanup (); return -1; } while(1) { con = accept(s, (struct sockaddr*)&addr, &addr_size); hThread = CreateThread( NULL, 0, MyThreadFunction, (LPVOID)con, 0, (LPDWORD)&dwThreadId); } closesocket(s); WSACleanup (); return (1); } DWORD WINAPI MyThreadFunction( LPVOID lpParam ) { SOCKET s; char buffer[128]; int n, i; s = (SOCKET)lpParam; while(1) { n = recv(s, buffer, sizeof(buffer), 0); if (n == SOCKET_ERROR) { fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError()); fprintf(stderr,"Server: resetting socket\n"); closesocket(s); break; } else printf("Server: recv() is OK.\n"); if (n == 0) { printf("Server: Client closed connection.\n"); closesocket(s); break; } else { printf("Server: Received %d bytes from client\n", n); for(i=0;i<n;i++) fprintf(stderr,"data[%d]=%d", i, (unsigned char)buffer[i]); } } return 0; }
pinball_elf Δημοσ. 12 Μαΐου 2010 Δημοσ. 12 Μαΐου 2010 Ο παρακάτω κώδικας έιναι ένα παράδειγμα ενός πολυνηματικού server σε C για Windows όπως το περιγράφει ο RubiksCube: > #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <winsock2.h> #include <string.h> DWORD WINAPI MyThreadFunction( LPVOID lpParam ); int main (vold) { SOCKET s, con; struct sockaddr_in addr; // the address structure for a TCP socket size_t addr_size; DWORD dwThreadId; HANDLE hThread; int threadCount = 0; // Must be done at the beginning of every WinSock program WSADATA w; // used to store information about WinSock version int error = WSAStartup (0x0202, &w); // Fill in w if (error) { // there was an error return -1; } else fprintf(stdout, "Winsock v%d.%d initialized\n", LOBYTE(w.wVersion), HIBYTE(w.wVersion)); if (w.wVersion != 0x0202) { // wrong WinSock version! WSACleanup (); // unload ws2_32.dll return -1; } s = socket (AF_INET, SOCK_STREAM, 0); // Create socket addr.sin_family = AF_INET; // Address family Internet addr.sin_port = htons (5555); // Assign port 5555 to this socket addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination addr_size = sizeof(addr); if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) { // error WSACleanup (); // unload WinSock return -1; // quit } if (listen(s, 5) == SOCKET_ERROR) /* 5 = max length of the queue of pending connections */ { // error! unable to listen WSACleanup (); return -1; } while(1) { con = accept(s, (struct sockaddr*)&addr, &addr_size); hThread = CreateThread( NULL, 0, MyThreadFunction, (LPVOID)con, 0, (LPDWORD)&dwThreadId); } closesocket(s); WSACleanup (); return (1); } DWORD WINAPI MyThreadFunction( LPVOID lpParam ) { SOCKET s; char buffer[128]; int n, i; s = (SOCKET)lpParam; while(1) { n = recv(s, buffer, sizeof(buffer), 0); if (n == SOCKET_ERROR) { fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError()); fprintf(stderr,"Server: resetting socket\n"); closesocket(s); break; } else printf("Server: recv() is OK.\n"); if (n == 0) { printf("Server: Client closed connection.\n"); closesocket(s); break; } else { printf("Server: Received %d bytes from client\n", n); for(i=0;i<n;i++) fprintf(stderr,"data[%d]=%d", i, (unsigned char)buffer[i]); } } return 0; }
ntaryl Δημοσ. 12 Μαΐου 2010 Δημοσ. 12 Μαΐου 2010 Σε ευχαριστω πολυ για τον κωδικα . Απ οτι βλεπω υπαρχει ενα Loop που κανει accept ενα request και μετα Δημιουργει ενα νεο thread για να στειλει και να λαβει καλο βραδυ Υ.γ παω για διαβασμα
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.