2013-07-05 2 views
-1

Я пытаюсь реализовать Socket, где клиент отправляет предложение серверу, а сервер отвечает на два целых valeus pcount и ncount. Я могу получить оба этого, но первая операция recv получает оба значения, а также добавляет некоторые другие данные в буфер.Выполнение последовательной операции отправки и получения в программировании сокетов TCP

client.cpp

#include <fcntl.h> 
    #include <string.h> 
    #include <stdlib.h> 
    #include <errno.h> 
    #include <stdio.h> 
    #include <netinet/in.h> 
    #include <resolv.h> 
    #include <sys/socket.h> 
    #include <arpa/inet.h> 
    #include <unistd.h> 

    char *foo(char* buf) 
    { 
     char buffer[1024]; 
     char *a='\0'; 
     char *c=buf; 
     strcpy(buffer,buf); 

     int host_port= 1102; 
     char* host_name="127.0.0.1"; 

     struct sockaddr_in my_addr; 

     //char buffer[1024]; 
     int bytecount; 
     int buffer_len=0; 

     int hsock; 
     int * p_int; 
     int err; 

     hsock = socket(AF_INET, SOCK_STREAM, 0); 
     if(hsock == -1){ 
      printf("Error initializing socket %d\n",errno); 
      goto FINISH; 
     } 

     p_int = (int*)malloc(sizeof(int)); 
     *p_int = 1; 

     if((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1)|| 
      (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1)){ 
      printf("Error setting options %d\n",errno); 
      free(p_int); 
      goto FINISH; 
     } 
     free(p_int); 

     my_addr.sin_family = AF_INET ; 
     my_addr.sin_port = htons(host_port); 

     memset(&(my_addr.sin_zero), 0, 8); 
     my_addr.sin_addr.s_addr = inet_addr(host_name); 

     if(connect(hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1){ 
      if((err = errno) != EINPROGRESS){ 
       fprintf(stderr, "Error connecting socket %d\n", errno); 
       goto FINISH; 
      } 
     } 

     //Now lets do the client related stuff 

     buffer_len = 1024; 
     memset(buf, '\0', buffer_len); 

     buf[strlen(buf)-1]='\0'; 

     if((bytecount=send(hsock, buffer, strlen(buffer),0))== -1){ 
      fprintf(stderr, "Error sending data %d\n", errno); 
      go 

    to FINISH; 
      } 
      printf("Sent bytes %d\n", bytecount); 
     //------- 


    // may Needs to empty content of buffer here but dont know how to do. Tried with fflush, free(buffer) but does not work 

//Two recv function which ideally recv pcount and ncount subsequently 

      if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){ 
       fprintf(stderr, "Error receiving data %d\n", errno); 
       goto FINISH; 
      } 
      printf("Recieved bytes %d\nReceived string \"%s \n", bytecount, buffer); 

    //Needs to empty content of buffer here but dont know how to do. Tried with fflush, free(buffer) but does not work 

if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){ 
      fprintf(stderr, "Error receiving data %d\n", errno); 
      goto FINISH; 
     } 
     printf("Recieved bytes %d\nReceived string \"%s \n", bytecount, buffer); 




     close(hsock); 

    FINISH: 
    ; 

    return buffer; 
    } 

И server.cpp:

#include <fcntl.h> 
    #include <string.h> 
    #include <stdlib.h> 
    #include <errno.h> 
    #include <stdio.h> 
    #include <netinet/in.h> 
    #include <resolv.h> 
    #include <sys/socket.h> 
    #include <arpa/inet.h> 
    #include <fcntl.h> 
    #include <string.h> 
    #include <stdlib.h> 
    //#include <errno.h> 
    #include <stdio.h> 
    #include <netinet/in.h> 
    #include <resolv.h> 
    #include <sys/socket.h> 
    #include <unistd.h> 
    //#include <sstream.h> 
    #include <pthread.h>       
    #include "serverFunction.cpp" 
    #include "serverFunction2.cpp" 
    #include <iostream> 
    #include <sstream> 
    #include <cstdio> 
    using namespace std; 
    void *SocketHandler(void *); 

    int main(int argv, char **argc) 
    { 
     int host_port = 1102; 
     char buf[20]; 
     int k; 
     struct sockaddr_in my_addr; 

     int hsock; 
     int *p_int; 
     int err; 

     socklen_t addr_size = 0; 
     int *csock; 
     sockaddr_in sadr; 
     pthread_t thread_id = 0; 


     hsock = socket(AF_INET, SOCK_STREAM, 0); 
     if (hsock == -1) { 
     printf("Error initializing socket %dn", errno); 
     goto FINISH; 
     } 

     p_int = (int *) malloc(sizeof(int)); 
     *p_int = 1; 

     if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) { 
     printf("Error setting options %dn", errno); 
     free(p_int); 
     goto FINISH; 
     } 
     free(p_int); 

     my_addr.sin_family = AF_INET; 
     my_addr.sin_port = htons(host_port); 

     memset(&(my_addr.sin_zero), 0, 8); 
     my_addr.sin_addr.s_addr = INADDR_ANY; 

     if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) { 
     fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno); 
     goto FINISH; 
     } 
     if (listen(hsock, 10) == -1) { 
     fprintf(stderr, "Error listening %dn", errno); 
     goto FINISH; 
     } 
     //Now lets do the server stuff 

     addr_size = sizeof(sockaddr_in); 

     while (true) { 
     printf("waiting for a connectionn\n"); 
     csock = (int *) malloc(sizeof(int)); 
     if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) { 
      printf("---------------------nReceived connection from %s\n", inet_ntoa(sadr.sin_addr)); 
      pthread_create(&thread_id, 0, &SocketHandler, (void *) csock); 
      pthread_detach(thread_id); 
     } else { 
      fprintf(stderr, "Error accepting %dn", errno); 
     } 
     } 

     FINISH: 
     ; 
    } 

    void *SocketHandler(void *lp) 
    { 

     int result=0; 
     //std::stringstream ss; 
     int *csock = (int *) lp; 
     char buf[20]; 
     int k; 
    // char *target="my name is khan"; 
     char *str; 
     char *str2; 
     int pcount = 0, ncount = 0; 

     char buffer[1024]; 
     int buffer_len = 1024; 
     int bytecount; 

     int i = 0,t=0,q=0; 
     int j = 0; 
     char *ch[50] = { 0 }; /* stores references to 50 words. */ 
     char *ch2[50] = { 0 }; 

     char *word = strtok(buffer, " "); 
     char *word2 = strtok(buffer, " "); 

     char *portstring1=(char *)malloc(sizeof(buffer)); 
     char *portstring2=(char *)malloc(sizeof(buffer)); 

     memset(buffer, 0, buffer_len); 
     if ((bytecount = recv(*csock, buffer, buffer_len, 0)) == -1) { 
     fprintf(stderr, "Error receiving data %d \n", errno); 
     goto FINISH; 
     } 
     printf("Received bytes %d \n Received string %s \n ", bytecount, buffer); 
     /* stores references to 50 words. */ 
     word = strtok(buffer, " "); 

     while ((NULL != word) && (50 > i)) { 
     ch[i] = strdup(word); 
     //printf("%s n", ch[i]); 

     str = BoyerMoore_positive(ch[i], strlen(ch[i]) - 1); 
     str2= BoyerMoore_negative(ch[i], strlen(ch[i]) - 1); 
     if (str == NULL) 
      t++; 
     else { 
       printf("%s \n", ch[i]); 
      // puts("true"); 
      pcount += 1; 
      printf("Positive count is: %d \n",pcount); 
     } 

     if(str2== NULL) 
      q++; 
     else { 
       printf("%s \n", ch[i]); 
      // puts("true"); 
      ncount += 1; 
      printf("Nagative count is: %d \n",ncount); 
     } 

     i++; 
     word = strtok(NULL, " "); 
     } 

//I want to send pcount and ncount values to client 

     **sprintf(portstring1, "%d", pcount); 

     if ((bytecount = send(*csock, portstring1, 1, 0)) == -1) { 
     fprintf(stderr, "Error sending data %d\n", errno); 
     goto FINISH; 
     } 

     sprintf(portstring2, "%d", ncount); 

      if ((bytecount = send(*csock, portstring2, strlen(portstring2), 0)) == -1) { 
     fprintf(stderr, "Error sending data %d\n", errno); 
     goto FINISH; 
     }** 

     FINISH: 
     free(csock); 
     return 0; 
    } 

Я получаю такой вывод:

Enter sentence to send to the server (press enter) 
critic worst nice 
Sent bytes 18 
Recieved bytes 2 
Received string 12itic worst nice //Here there should be only 1 2. Why 'itic ..' gets appended. And why 1 and 2 both does not get printed one after another 
+0

Он не добавляет некоторые другие данные в буфер. Хлам уже был. – EJP

ответ

0

@Joni и David- Спасибо за вашу поддержку!

Проблема решена:

на отправителе:

int ar[2]; 

if ((bytecount = send(*csock, (char *)ar, 2 *sizeof(int), 0)) == -1) { // Here we cant send lenth-1. It consider exact 
    fprintf(stderr, "Error sending data %d\n", errno); 
    goto FINISH; 
    } 

на стороне приемника:

if((bytecount = recv(hsock, ar, 2 * sizeof(int), 0))== -1){ 
     fprintf(stderr, "Error receiving data %d\n", errno); 
     goto FINISH; 
    } 


    for(k=0;k<2;k++) 
    { 
     printf("count is :%d",ar[k]); 
    } 

просто взял и массив, теперь я могу послать любое получить любое количество значений! Это очень просто!

1

Функция RECV не добавляет пустой символ, чтобы прекратить полученную строку. Вы должны добавить его самостоятельно, как это:

if((bytecount = recv(hsock, buffer, buffer_len-1, 0))== -1){ 
      fprintf(stderr, "Error receiving data %d\n", errno); 
      goto FINISH; 
} 
buffer[bytecount]=0; 

Обратите внимание на -1 в буфере Len, чтобы убедиться, что есть место для NUL характера.

+0

Да, я сделал это, и это улучшилось. Когда я помещаю «memset (buffer, 0, 1024)»; после первого recv() он получает точно первые отправленные значения с сервера. Но не отображает значения второго счета, отправленные с сервера! После первого recv() снова я помещаю «memset (buffer, 0, 1024)»; а затем recv(), в этом случае он переходит в режим постоянного прослушивания! – user123

+0

Если вы хотите, чтобы первый вызов recv читал только один символ, вы должны передать 1 вместо buffer_len в recv. – Joni

+0

Размер значений, которые я буду возвращать, может измениться. Итак, как я мог его процедить? Возможно ли, что сначала я отправил размер сообщения, которое я хочу отправить, а затем recv(), что только много суммы? Но в этом случае проблема может иметь тип данных. В сокете я могу отправлять только символы char *, а не int! – user123

1

Вы забыли разработать и реализовать протокол. Магическая сеть не работает. Если у вас есть понятие сообщения на уровне приложения, вам необходимо написать код для отправки и получения сообщений на уровне приложений. Вы этого не сделали, так что, конечно, этого не произойдет.

также:

printf("Received bytes %d \n Received string %s \n ", bytecount, buffer); 

%s спецификатор формата только для строк C-стиле. Он не подходит для произвольных данных. Как узнать, сколько байтов для печати?

+0

Можете ли вы рассказать мне, как код для сообщения уровня приложения для отправки и повтора? – user123

+0

Ознакомьтесь со спецификациями других протоколов, которые имеют сообщения уровня приложения, такие как SMTP, HTTP, IRC и т. Д. Вы должны определить, что такое сообщение и как они отмечены, а затем написать код для определения границ сообщений. –

+0

Я искал googled, но не мог найти связанных с моим материалом. Не могли бы вы рассказать мне, что именно я должен искать? – user123

Смежные вопросы