LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 10-24-2004, 03:53 AM   #1
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Rep: Reputation: 15
Networking&Text files; A string or two, and LOTS of int's


Hey all, I want to thank anyone who helps out ahead of time. Thanks!

I have a two part problem, but first. I am writing a program that computes primes and then computes factors. I am looking to be able to port this over many computers similiar to a cluster, but without the need for a cluster. I am going to have one program running as the server and another program running on each client. The server is going to divide the work of computing the primes and record them to a list. Then compute the factors of the non-prime numbers. My problem is that I need to find a way to send a client a long list of numbers in a single packet(so as to not cause massive latancy[sorry for spelling]). Then the server is going to record the primes into one file, and the factors into another file. I need to be able to read and write to the files so they must be in a logical format. Here is what I'm hoping to files to look somewhat like:

Primes.dat:
1
2
3
5
7
11
13
17
19
23
etc.......

Factors.dat:
4=2x2
6=2x3
8=2x4
9=3x3
10=2x5
12=2x6,3x4
14=2x7
15=3x5
16=2x8,4x4
etc......

I need to be able to read the prime numbers and add them into a vector so that I can send them to a client. This way I can divide up the work. For instance:

Server says to Client1"check the range [100-200] with primes [5,7,11,13].
Server says to Client2"check the range [200-300] with primes [5,7,11,13].
etc....

I have divised a way to send a one byte packet to a client which would tell it what kind of data to expect and what it's job will be. Like one control packet would tell it that it is about to be sent it's range. Then it is sent '100-200' The next packet would be a control packet telling it that it's list of primes will be updated. then it is sent '5,7,11,13'.

Any Ideas? Anyone?
 
Old 10-24-2004, 10:20 AM   #2
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,539

Rep: Reputation: 149Reputation: 149
Doable, but why not to send everything as one message? You can use a simple format like (example):
Code:
2\n100-200\n5,7,11,13\n
In this case 2 may be a specific task (you can assign number to all possible actions).
Is there a reason you want to divide the messages?
 
Old 10-24-2004, 01:58 PM   #3
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Original Poster
Rep: Reputation: 15
WOW!! Hehe, I can be easily excited sometimes. If it is possible to send it in that format it would be amazing. My problem is that I have limited knowledge of the code that would parse(or other reasonable word) the information from that packet from the char buffer into something usable.

like:

char buffer[big_global_decent_buffer_size_here];
buffer now equals: 2\n100-200\n5,7,11,13\n

how to I get that in to 3 int's and a vector?
int control_number, low_range, high_range;
vector<int> primes;

how do I get it to now be:
control_number=2;
low_range=100;
high_range=200;
primes=5,7,11,13;

Here is what I have for the basic testing server so far:

Code:
int startupServerForListening(unsigned short port);
   void shutdownServer(int socket);
#include <winsock2.h>
#include <stdio.h>

#define RECV_ON_PORT 7655
#define MAX_MESSAGE_SIZE 4096
           
   void main() {
           
      printf("Welcome to Will's Char Buffer Server!\n");
   
      int serverSocket;
   
      serverSocket = startupServerForListening(RECV_ON_PORT);
      printf("%d",serverSocket);
   
      if (serverSocket == -1) {
         printf("Network Startup Failed!\nProgram Terminating\n");
         return;
      }
      int clientSocket;
      while(true){
         clientSocket = accept(serverSocket, 0, 0);
      
         if (clientSocket == SOCKET_ERROR) {
            printf("Accept Failed!\n");
         }
      
         int nBytes;
      
         char buffer[MAX_MESSAGE_SIZE];
      
         unsigned long messageSize;
      
         nBytes = recv(clientSocket, (char*)&messageSize, sizeof(messageSize), 0);
         if (nBytes == SOCKET_ERROR) {
            printf("Recv Failed!\n");
         }
      
      // remember to fix byte ordering since this is a number
         messageSize = ntohl(messageSize);
      
         nBytes = recv(clientSocket, buffer, messageSize, 0);
      
      // check for errors
         if (nBytes == SOCKET_ERROR) {
            printf("Recv Failed!\n");
         }
         buffer[messageSize] = '\0';
      
         if(messageSize==1){
            char letter=buffer[0];
            switch(letter){
               case '1':
                  printf("you sent the letter 1\n");
            }
         }
         else
         {
            printf("Message Received : %s\n", buffer);
         }
      }
      closesocket(clientSocket);
   
      shutdownServer(serverSocket);
   
      printf("Press any key to continue ...\n");
      getchar();
   }
           
   int startupServerForListening(unsigned short port) {
           
   // an error code we will use to get more information about our errors
   // the winsock data structure
      WSAData wsaData;
   // startup winsock
      if (WSAStartup(MAKEWORD(2, 2), &wsaData) == SOCKET_ERROR) {
         printf("Could Not Start Up Winsock!\n");
         return -1;
      }
   // create my socket
      int mySocket = socket(AF_INET, SOCK_STREAM, 0);
   // make sure nothing bad happened
      if (mySocket == SOCKET_ERROR) {
         printf("Error Opening Socket!\n");
         return -1;
      }
   // the address structure
      struct sockaddr_in server;
   // fill the address structure with appropriate data
      server.sin_family = AF_INET;
      server.sin_port = htons(port);
      server.sin_addr.s_addr = INADDR_ANY;
   // and now bind my socket
      if (bind(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
         printf("Bind Failed!\n");
         closesocket(mySocket);
         return -1;
      }
   // mark my socket for listening
      if (listen(mySocket, 5) == SOCKET_ERROR) {
         printf("Listen Failed!\n");
         closesocket(mySocket);
         return -1;
      }
      printf("Server Started\n");
      return mySocket;
   }
           
   void shutdownServer(int socket) {
           
   // close our socket
      closesocket(socket);
   // shut down winsock
      WSACleanup();
      printf("Server Shutdown\n");
   }
I am using a modified piece of code found scattered over many winsock tutorials. Feel free to use it how ever you may wish.
 
Old 10-24-2004, 03:31 PM   #4
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,539

Rep: Reputation: 149Reputation: 149
The code will look like this:
Code:
int nBytes=recv(clientSocket,buffer,MAX_MESSAGE_SIZE,0);
//check for error

//first like - control number
control_number=0;
int i=0; //position in buffer
while(buffer[i]!='\n') {
    if(i>=MAX_MESSAGE_SIZE) error();
    if(isDigit(buffer[i])){
        control_number=charToInt(buffer[i])*10+control_number;
        i++;
    } else error();
}
i++;
while(buffer[i]!='-'){
   if(i>=MAX_MESSAGE_SIZE) error();
   if(isDigit(buffer[i])){
        low_range=charToInt(buffer[i])*10+low_range;
        i++;
    } else error();
}
i++;
while(buffer[i]!='\n'){
   if(i>=MAX_MESSAGE_SIZE) error();
   if(isDigit(buffer[i])){
        high_rangee=charToInt(buffer[i])*10+high_range;
        i++;
    } else error();
}
int count=0;
while(buffer[i]!='\n'){
   while((buffer[i]!=',')&&(buffer[i]!='\n'){
       if(i>=MAX_MESSAGE_SIZE) error();
       if(isDigit(buffer[i])){
           primes[count]=charToInt(buffer[i])*10+primes[count];
           i++;
       } else error();
  }
  count++;
}
Notes: you'll need to define the following functions:
isDigit - true if the char given as parameter is digit
charToInt - converts char (digit) to int
error - does something when there's an error (the message is incorrect)

BTW If winsock works like Unix sockets, your recv syntax looks wrong. Second parameter is buffer, not its size.
 
Old 10-24-2004, 07:00 PM   #5
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Original Poster
Rep: Reputation: 15
The winsock thing, check it again. I've designed it to send a number first that will tell how long the data file will be, then send the data file. It works, I've tested it thoroughly. Unix is different? hmm... Then I guess it should be interesting when I port this to unix and linux.

Thanks a lot for that section of code, that should be awesome. Hmm....

Ok, I think I can write the code for the charToInt() pretty easily it would just be a 10-11 case switch statement, and the isDigit() would be the same. Hmm, But I'm wondering about your code.

Is this what you meant?
Code:
while(buffer[i]!='-'){
   if(i>=MAX_MESSAGE_SIZE) error();
   if(isDigit(buffer[i])){
        low_range=low_range*10+charToInt(buffer[i]);
        i++;
    } else error();
}
it was a simple switch of the place of the digit, all is fine.

Now, what about the code that would save to a data file? I'm thinking that a very similiar section of code would work very well. What I was thinking is that the client would use a single control number to send the primes, ie:3. and another number to send the factors, ie:4.

I wanted to use these control numbers so that if and when my program needs to send extremely large amounts of data it could send it in parts and use to the control numbers to signify what that data means.
 
Old 10-25-2004, 04:37 PM   #6
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,539

Rep: Reputation: 149Reputation: 149
Quote:
Originally posted by quentusrex
Ok, I think I can write the code for the charToInt() pretty easily it would just be a 10-11 case switch statement, and the isDigit() would be the same. Hmm, But I'm wondering about your code.

Is this what you meant?
The functions are easy to write for ASCII, but get more complicated when we think about Unicode. With digits it's easier that with letters, but still...
Not sure what do you mean by the code fragment. It looks rather OK
Quote:
Now, what about the code that would save to a data file? I'm thinking that a very similiar section of code would work very well. What I was thinking is that the client would use a single control number to send the primes, ie:3. and another number to send the factors, ie:4.
Saving to a file is very easy - you don't need to check the numbers if they're really numbers...Reading can be done using nearly the same code with file handler instead of socket (that's the beauty of Unix design - socket and file are used in the same way).

Quote:
I wanted to use these control numbers so that if and when my program needs to send extremely large amounts of data it could send it in parts and use to the control numbers to signify what that data means.
It looks you can do it easily
 
Old 10-25-2004, 05:44 PM   #7
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Original Poster
Rep: Reputation: 15
What about a technique for finding a server? I think I've heard it called subnet broadcasting, but I could be wrong. I need some way to find the server without manually telling the client the ip of the server. Any ideas?
 
Old 10-25-2004, 05:45 PM   #8
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Original Poster
Rep: Reputation: 15
Right now it works easily because I am testing it on the same computer. Both client and server are running on one computer. But i need a way to move them to two different computesr.
 
Old 10-26-2004, 09:17 AM   #9
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,539

Rep: Reputation: 149Reputation: 149
You have two options: giving the server's IP as parameter (or in a configuration file) or broadcast. The second option has limitations - increased traffic and works only in the same subnet (if server and client are in different ones it won't work).

To use broadcast in your code (again, in Unix socket implemantation) you need to setup a socket with broadcast address (like 192.168.1.255 when network is 192.168.1.0), set the socket to broadcast (setsockopt with SO_BROADCAST). Then you can just use sendto to set the data as usual. Of course, only server should wait for the data.
 
Old 10-27-2004, 06:19 AM   #10
quentusrex
Member
 
Registered: Aug 2004
Location: Seattle, Washington
Posts: 101

Original Poster
Rep: Reputation: 15
Thanks Mara, you've been a wonderful help. Thanks soo much for the sample code you gave me it really helped. I completed the project I was working on and now feel satisfied with it's completion. But, as with the case with many great learners, I have found another project. It too deals with networking.

As for the final question about how to send a packet to all computers on a LAN or subnet you would send the packet to the broadcast address. This can be found on Windows by typing 'ipconfig' at a DOS prompt or in Linux by typing 'ifconfig' in the shell.

I will post a new thread with a discription of my new project.

Thanks all!!!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Convert DOS text files to UNIX text files ta0kira Linux - Software 7 03-15-2011 12:42 PM
Show LFs & TABs in listing text files fiomba Linux - Software 0 12-02-2005 04:58 AM
batch append string to the end of a determined line in text files osio Programming 6 06-30-2005 10:28 AM
CLI copy & paste between text files? David the H. Linux - General 3 09-15-2004 01:05 PM
Find string pattern in directory of text files magnum818 Linux - Newbie 2 10-15-2003 09:19 PM


All times are GMT -5. The time now is 02:30 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration