Socketprogrammierung in C

Status
Nicht offen für weitere Antworten.

reavez

Gesperrt
hallo,

ich hab folgenden mustercode zur socketprogrammierung.
das program läuft einwandfrei unter linux. server läuft im hintergrund und wartet auf client. client connected mit ip adresse und port des servers und kann fileliste und files vom server herunterladen. dem server wird vorher die directory angegeben.
zb.: ./server 127.0.0.1 /bin/user/...
client startet mit ./client 127.0.0.1 Portnr

jetzt muss ich den code so verändern, dass parallele requests vom client ermöglicht werden (so gehts nur mit einem client). am besten mit fork.
doch wie? dann soll ich noch im server eine maximale bandbreite (in kbytes) pro client angeben. falls limit überschritten wird -> sleep befehl.

könnte mir jemand mit dem code helfen, bzw. gibt es im netz wo socket samples mit fork prozess?




server.c
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#define BUF 1024
#define STRINGTRANSBUF 1024

typedef struct ReturnCommand
{
 double cmd;
 char parameter[BUF];
}retc;

char* itoa (int value, char *buffer, int radix);

int main (int argc, char **argv)
{
  int create_socket, new_socket;
  socklen_t addrlen;
  char buffer[BUF],filename[BUF],path[BUF];
  int size, fd,x;
  struct sockaddr_in address, cliaddress;
 struct stat st;
 struct dirent *ep;
 retc recive,answer;
 DIR *dp;
 double bytesleft=0,bytesread=0;

 /* we need a valid port between 1 and 65535 and a directory */
  if( argc < 3 || atoi(argv[1]) > 65535 || atoi(argv[1]) < 1)
 {
	 printf("Usage: %s <Port> <Directory>\n", argv[0]);
	 exit(EXIT_FAILURE);
  }
 /* store the directory in path */
 strcpy(path,argv[2]);
 create_socket = socket (AF_INET, SOCK_STREAM, 0);

  memset(&address,0,sizeof(address));
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = INADDR_ANY;
  address.sin_port = htons (atoi(argv[1]));

  if (bind ( create_socket, (struct sockaddr *) &address, sizeof (address)) != 0) {
	 perror("bind error");
	 return EXIT_FAILURE;
  }
  listen (create_socket, 5);
  
  addrlen = sizeof (struct sockaddr_in);

  while (1) {
	 printf("Waiting for connections...\n");
	 new_socket = accept ( create_socket, (struct sockaddr *) &cliaddress, &addrlen );
	 if (new_socket > 0)
	 {
		printf ("Client connected from %s:%d...\n", inet_ntoa (cliaddress.sin_addr),ntohs(cliaddress.sin_port));
		strcpy(buffer,"Welcome to filetrans the ultimate file transfer solution.\n");
		send(new_socket, buffer, strlen(buffer),0);
	 }
	 do {
		size = recv (new_socket, &recive, sizeof(retc), 0);  
		if( size > 0)
		{
		   if (recive.cmd == 1) 
	  {
		recive.parameter[strlen(recive.parameter)] = 0;
		strcpy(filename,path);
		strcat(filename,recive.parameter);  
	   
	   fd = open(filename, O_RDONLY);
		size = 0;
	   if (stat(filename,&st) < 0 || fd == -1)
	   {
		printf("File %s could not be read.\n",filename);
		answer.cmd = 0;
	   }
	   else
	   {
		answer.cmd = st.st_size;   
		bytesleft = st.st_size;
		strcpy(answer.parameter,recive.parameter);
	   }
	   while (size != sizeof(answer)) size = send(new_socket, &answer, sizeof(answer),0); 
	   if (answer.cmd > 0)
	   {
		while (bytesleft > 0) 
		{
		 size=0;
		 bytesread = read(fd,buffer,STRINGTRANSBUF);
		 bytesleft -= bytesread;
		 do 
		 {
		  size += send(new_socket,buffer+size,bytesread - size,0);
		 }while (size < bytesread);
		}
		printf("File %s sent.\n",filename);
	   }
	  }
	  else if (recive.cmd == 2) /* list command recived */
	  {
		dp = opendir (path);
	   if (dp != NULL)
	   {
		while ((ep = readdir (dp)) != NULL)  
		{
#ifdef _DIRENT_HAVE_D_TYPE   
		  switch(ep->d_type)
		  {
		   case DT_REG: strcpy(answer.parameter,"<File>\t");
				 break;
		   case DT_DIR: strcpy(answer.parameter,"<Dir>\t");
				 break;
		   default: strcpy(answer.parameter,"\t\t");
				 break;
		  }		  
#endif
		  strcpy(filename,path);
		   strcat(filename,ep->d_name);
		  x = stat(filename,&st);   /* get filesize */
		  strcat(answer.parameter,ep->d_name);
		  answer.cmd = st.st_size;
		  size=0;
		  while (size != sizeof(answer)) size = send(new_socket, &answer, sizeof(answer),0); 
		}
		answer.cmd = -1; 
		closedir(dp);
		printf("Directory %s sent.\n",path);
	   }
	   else
	   {
		perror ("Could not open directory\n");
		answer.cmd = -2;
	   }
	   size=0;
	   while (size != sizeof(answer)) size = send(new_socket, &answer, sizeof(answer),0); 
	  }
		}
		else if (size == 0)
		{
		   printf("Client closed remote socket\n");
		   break;
		}
		else
		{
		   perror("recv error");
		   return EXIT_FAILURE;
		}
	 } while (recive.cmd  != -1);
	 close (new_socket);
  }
  close (create_socket);
  return EXIT_SUCCESS;
}

-------------------------------------------------------------------

client.c
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#define BUF 1024
#define STRINGTRANSBUF 1024

typedef struct ReturnCommand
{
 double cmd;
 char parameter[BUF];
}retc;

retc phraser(char *String);
int main (int argc, char **argv)
{
  int create_socket;
  char buffer[BUF],filename[BUF];
  struct sockaddr_in address;
  int size,i,fd;
 double bytesleft=0;
 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 
 retc command,recive;
 
 if( argc < 3 || atoi(argv[2]) > 65535 || atoi(argv[2]) < 1)
 {
	 printf("Usage: %s <ServerAdresse> <Port>\n", argv[0]);
	 exit(EXIT_FAILURE);
  }
 // creating the socket
  if ((create_socket = socket (AF_INET, SOCK_STREAM, 0)) == -1)
  {
	 perror("Socket error");
	 return EXIT_FAILURE; 
  }
  */
  memset(&address,0,sizeof(address));
  address.sin_family = AF_INET;
  address.sin_port = htons */ (atoi(argv[2]));
  inet_aton (argv[1], &address.sin_addr);
 if (connect ( create_socket, (struct sockaddr *) &address, sizeof (address)) == 0)
  {
	 printf ("Connection with server (%s) established\n", inet_ntoa (address.sin_addr));
	 size=recv(create_socket,buffer,BUF-1, 0);
	 if (size>0)
	 {
		buffer[size]= '\0';
		printf("%s",buffer);
	 }
  }
  else
  {
	 perror("Connect error - no server available");
	 return EXIT_FAILURE;
  } */
 printf("Enter a command or type help for a list of aviable commands.\n\n");
  do
 {
	 printf ("> ");
	 fgets (buffer, BUF, stdin);
   for (i=0;i<strlen(buffer);i++) if (buffer[i] == ' ') { break; } else { buffer[i] = toupper(buffer[i]); }	  command = phraser(buffer);
   
   if (command.cmd != 0) send(create_socket, &command, sizeof(retc), 0); 
   if (command.cmd == 1) 
   {
	 size = 0;
	 while (size != sizeof(recive)) size = recv(create_socket,&recive,sizeof(recive),0); 
	bytesleft = recive.cmd;
	if (bytesleft > 0)  
	{
	 strcpy(filename,recive.parameter);
	 fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC | O_CREAT, mode);
	 if (fd == -1) { perror ("Error opening file "); return EXIT_FAILURE;}
	 while (bytesleft > 0)
	 {
	  size=recv(create_socket,buffer,STRINGTRANSBUF, 0);
	  write(fd,buffer,size);
	  bytesleft -= size; 
	 }
	 close(fd);
	 printf("File %s recived.\n",filename);
	}
	else
	{
	 printf("File could not be found or opend!\n");
	}
   }
   else if (command.cmd == 2)
   {
	 do
	{
	 size = 0;
	 while (size != sizeof(recive)) size = recv(create_socket,&recive,sizeof(recive),MSG_WAITALL); 
	 if (recive.cmd >= 0)printf("%.0lf\t\t%s\n",recive.cmd,recive.parameter); 
	}while (recive.cmd >= 0); 
	if (recive.cmd <-1) printf("Could not open directory.\n");
   }
  } 
  while (command.cmd != -1);
  
 close (create_socket);
  return EXIT_SUCCESS;
}
/* phrase the user input */
retc phraser(char *String)
{
 retc command;
 
 if (strncmp(String,"GET",3)==0)
 {
  if (String[3] == '\n' || String[4] == '\n')
  {
   command.cmd = 0;
   printf("Usage: get <filename>\n");
  }
  else
  {
   command.cmd = 1;
   strcpy(command.parameter,String + 4);
   command.parameter[strlen(command.parameter)-1] = 0;
  }
 }
 else if (strcmp(String,"LIST\n")==0)
 {
  command.cmd = 2;
 }
 else if (strcmp(String,"HELP\n")==0)
 {
  command.cmd = 0;
  printf("List of aviable commands:\n");
  printf("help\t\t- this help message\n");
  printf("get <filename>\t- get file <filename> from server\n");
  printf("list\t\t- lists aviable files on the server\n");
  printf("quit\t\t- closes active connection and exits program\n");
 }
 else if (strcmp(String,"QUIT\n")==0)
 {
  command.cmd = -1;
  printf("closing connection.\n");
 }
 else if (strcmp(String,"EXIT\n")==0)
 {
  command.cmd = -1;
  printf("closing connection.\n");
 }
 else
 {
  command.cmd=0;
  printf("Unknown command.\n");
 }
 return command;
}
 
moin


Hier gibt es schon enige Beispiele, und andere Hilfreiche Dinge zu dem Thema!
Suchfunktion ist das Zauberwort.


mfg
umbrasaxum
 
Zotteljedi hat nen komplette server da schon drinne mein ich, ansonsten hol dir das Buch was er da hat
Das kann ich einfach nur empfehlen das ist der Hammer

Und ich würde nicht fork() benutzen ...
eher select(), denn wenn bei fork() was schief geht bleibt der Client kleben oder du hast Zombies ...


gruß 2fast ...
 
hallo,

ich wollte mal den obigen socketserver testen. der sollte funktionieren, aber bei mir läuft da nicht was korrekt und zwar, wenn ich ein server-verzeichnis erstelle und dort einen file kopier, kann ich den nicht mittels client runterladen. ich bekomm die meldung "cannot read or open file" obwohl eh alles passt. könnte wer den server und client mal testen ob der bei euch ?
 
moin


Hast du eigentlich Windows oder Linux?
Und halte dich bitte mehr an die Groß und Kleinschribung!


mfg
umbrasaxum
 
hallo,
ich machs unter linux. groß, klein schreibung beachte ich natürlich. geht aber trotzdem irgendwie nicht :(

edit:
so habs zusammen bekommen. ich vergessen ein / vor dem dateinamen zu geben.

danke für den link. ich setz mich mal hin und mach den fork :)
 
Zuletzt bearbeitet:
Status
Nicht offen für weitere Antworten.
Zurück