LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Networking&Text files; A string or two, and LOTS of int's (https://www.linuxquestions.org/questions/programming-9/networking-and-text-files%3B-a-string-or-two-and-lots-of-ints-246607/)

quentusrex 10-24-2004 02:53 AM

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?

Mara 10-24-2004 09:20 AM

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?

quentusrex 10-24-2004 12:58 PM

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.

Mara 10-24-2004 02:31 PM

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.

quentusrex 10-24-2004 06:00 PM

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.

Mara 10-25-2004 03:37 PM

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 :)

quentusrex 10-25-2004 04:44 PM

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?

quentusrex 10-25-2004 04:45 PM

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.

Mara 10-26-2004 08:17 AM

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.

quentusrex 10-27-2004 05:19 AM

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!!!


All times are GMT -5. The time now is 01:41 AM.