2

I have a program that creates a socket (server and client program) and sends a message via a TCP port using that socket. My question is, how can I exchange multiple messages? Every time I send a message the port gets closed and I need to use another port to send another message.

For example, I have to send 2 numbers from the client to the server and the server needs to reply back the total sum of the numbers I send. How would I achieve sending undefined number or even 2 numbers over the SAME port?

Here are the codes (pretty much standard stuff):

Server:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

char* Itoa(int value, char* str, int radix) 
{
    static char dig[] =
      "0123456789"
      "abcdefghijklmnopqrstuvwxyz";
    int n = 0, neg = 0;
    unsigned int v;
    char* p, *q;
    char c;
    if (radix == 10 && value < 0) {
      value = -value;
      neg = 1;
    }
    v = value;
    do {
      str[n++] = dig[v%radix];
      v /= radix;
    } while (v);
    if (neg)
      str[n++] = '-';
    str[n] = '\0';
    for (p = str, q = p + (n-1); p < q; ++p, --q)
      c = *p, *p = *q, *q = c;
    return str;
}

void error (const char *msg)
{
    perror (msg);
    exit (1);
}
int main (int argc, char *argv[])
{
    if (argc < 2)
    {
        fprintf (stderr, "ERROR, no port provided\n");
        exit (1);
    }
    //nova varijabla za sumiranje primljenih brojeva
    int suma=0;

    int sockfd, newsockfd, portno,i;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    for (i=0;i<2;i++)
    {
        sockfd = socket (AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) error ("ERROR opening socket");
        memset ((char *) &serv_addr, 0, sizeof (serv_addr));
        portno = atoi (argv[1]);
        portno+=i;
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons (portno);
        if (bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) error ("ERROR on binding");
        //test za ispis otvorenog porta
        printf("Uspjesno otvoren localhost na portu %d\n", portno); 
        listen (sockfd, 5);
        clilen = sizeof (cli_addr);
        newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd < 0) error ("ERROR on accept");
        memset (buffer, 0, 256);
        n = read (newsockfd, buffer, 255);
        if (n < 0) error ("ERROR reading from socket");
        printf ("%d. proslan broj: %s\n", i+1, buffer);
//print
        suma=suma+atoi(buffer);
//radi!!        printf("suma je %d\n", suma);
//od klijenta: n = write (sockfd, buffer, strlen (buffer));
//char *  itoa ( int value, char * str, int base );
        Itoa(suma, buffer, 10);
        n = write (newsockfd, buffer, strlen(buffer));
        if (n < 0) error ("ERROR writing to socket");
        close (newsockfd);
        close (sockfd);
    }
    return 0;
}

Client:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void    error (const char *msg)
{
    perror (msg);
    exit (1);
}
int
main (int argc, char *argv[])
{
    if (argc < 3)
    {
        fprintf (stderr, "usage %s hostname port\n", argv[0]);
        exit (1);
    }
    int sockfd, portno, n,i;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];
    for (i=0;i<2;i++)
    {
        portno = atoi (argv[2]);
        sockfd = socket (AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        error ("Ne mogu otvoriti socket!");
        server = gethostbyname (argv[1]);
        if (server == NULL)
        {
            fprintf (stderr, "Greska, ne postoji!\n");
            exit (1);
        }
        memset ((char *) &serv_addr, 0, sizeof (serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy ((char *) server->h_addr,
        (char *) &serv_addr.sin_addr.s_addr,
        server->h_length);
        portno+=i;
        serv_addr.sin_port = htons (portno);
        if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
        error ("ERROR connecting");
        printf ("%d. broj za slanje: ", i+1);
        memset (buffer, 0, 256);
        fgets (buffer, 255, stdin);
        n = write (sockfd, buffer, strlen (buffer));
        if (n < 0)
        error ("ERROR writing to socket");
        memset (buffer, 0, 256);
        n = read (sockfd, buffer, 255);
        if (n < 0)
        error ("ERROR reading from socket");
        if (i==1) printf ("Suma iznosi: %s\n", buffer);
        close (sockfd);
    }
    return 0;
}

So, for example, I run the code and get this for the server side:

j@PC ~/Desktop/Mreze/Lab1/rijeseno $ ./server2 5000
Uspjesno otvoren localhost na portu 5000
1. proslan broj: 45

Uspjesno otvoren localhost na portu 5001
2. proslan broj: 56

j@PC ~/Desktop/Mreze/Lab1/rijeseno $ 

And on the client side:

j@PC ~/Desktop/Mreze/Lab1/rijeseno $ ./client2 localhost 5000
1. broj za slanje: 45
2. broj za slanje: 56
Suma iznosi: 101

I've tried putting a while loop so it loops the part with sending but without success. Please explain to me where should I even put it so it works. Thank you!

4

2 回答 2

2

这里有一个问题:

n = read (newsockfd, buffer, 255);

您所做的是执行一次读取,并且数据可能不完全可用。事实是,你需要读取数据,只要你完整接收到数据,或者检测到EOF条件(-1返回值)。

通常,您需要为接收部分编写更可靠的代码,因为流协议不能保证您的消息边界以任何形式保持。

这是一个(非常不理想,但很简单)读取数据的代码:

int readLine(int fd, char data[])
{
   size_t len = 0;
   while (len < maxlen)
   {
      char c;
      int ret = read(fd, &c, 1);
      if (ret < 0)
      {
          data[len] = 0;
          return len; // EOF reached
      }
      if (c == '\n')
      {
          data[len] = 0;
          return len; // EOF reached
      }
      data[len++] = c;
   }
}

以及用法示例:

char buffer[256];
int num1, num2;

readLine(newsockfd, buffer);
num1 = atoi(buffer);
readLine(newsockfd, buffer);
num2 = atoi(buffer);
于 2013-03-24T16:04:47.473 回答
1

首先将您的 connection() 函数放在 for 循环之前和 close() 之后。只是为了一个想法

connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)
for (i=0;i<n;i++){
 // do you introspection with server
 // actually send number to server 
}
// Code to read result: SUM from server
close (sockfd);
于 2013-03-24T15:37:50.307 回答