Προς το περιεχόμενο

Κόλλημα με Client / Server


KremTri

Προτεινόμενες αναρτήσεις

Δημοσ.

Ας μου εξηγησει καποιος ( 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::cry::cry::cry::cry::cry::cry::cry:

Δημοσ.

Η γενική ιδέα είναι:

Στο server έχεις ένα listening socket στο οποίο συνδέεται όποιος client θέλει. Από εκεί για κάθε client ξεκινάς ένα νέο thread με νέο socket και από αυτό το νεο socket επικοινωνείς με τον client. Δηλαδή συνολικά έχεις ν+1 threads όπου ν ο αριθμός των συνδεδεμένων clients.

Δημοσ.

Αρα θα χρειαστω για καθε client νεο socket και νεο thread!!!!

 

στην ρουτινα ομως του thread πως θα μπορεσω να επικοινωνω με καθε client ξεχωριστα χωρις να κολλάει?????

Δημοσ.
Αρα θα χρειαστω για καθε client νεο socket και νεο thread!!!!

 

στην ρουτινα ομως του thread πως θα μπορεσω να επικοινωνω με καθε client ξεχωριστα χωρις να κολλάει?????

 

Κάθε thread θα χειρίζεται έναν μόνο client. Τώρα αυτό το thread θα μπλοκάρει αν χρησιμοποιείς blocking IO (recvfrom()), μέχρι να λάβει δεδομένα από τον συγκεκριμένο client, θα τα επεξεργάζεται και θα ξαναμπλοκάρει (μέσα σε while loop).

Αν ψάξεις στο net για έναν πολύ απλό chatserver/client θα πάρεις μια ιδέα πώς ακρβώς λειτουργεί. Σε java τουλάχιστον ο κώδικας είναι πολύ μικρός.

Δημοσ.

οκ!!!!

 

εγω χρησιμοποιω την send(...) και την recv(...) που μάλλον ειναι blocking!!

ποιες συναρτησεις αντιστοιχα μπορω να χρησιμοποιησω που δεν ειναι blocking????

Δημοσ.

Eνδιαφερομαι και εγω για το θεμα αλλα οχι για Java.

Πιο συγκεκριμενα θελω να καταλαβω τον κωδικα .

Μπορει καποιος να αναρτησει κωδικα σε java αφου δεν εχω τον απαραιτητο compiler για να το μελετησω .

Ευχαριστω πολυ

 

 

P.s Εκτος και αν υπαρχει καποιος απλος compiler ετσι ωστε να μπορεσω να μελετησω τον κωδικα .Χωρις να χριεαστει να εγκαταστησω το Netbean

Δημοσ.

Ο παρακάτω κώδικας έιναι ένα παράδειγμα ενός πολυνηματικού 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; 
} 

Δημοσ.

Ο παρακάτω κώδικας έιναι ένα παράδειγμα ενός πολυνηματικού 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; 
} 

Δημοσ.

Σε ευχαριστω πολυ για τον κωδικα .

Απ οτι βλεπω υπαρχει ενα Loop που κανει accept ενα request και μετα Δημιουργει ενα νεο thread για να στειλει και να λαβει

καλο βραδυ

 

Υ.γ παω για διαβασμα

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...