elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Programa de Calculadora con sockets
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Programa de Calculadora con sockets  (Leído 6,654 veces)
rootLink

Desconectado Desconectado

Mensajes: 4


Ver Perfil
Programa de Calculadora con sockets
« en: 31 Agosto 2022, 18:38 pm »

Hola, estoy cursando la materia de redes en mi escuela, y el profesor es de esos que llegan y dicen lo que vas a hacer todo e semestre y no lo vuelve a ver hasta el final. En fin , hasta ahora eh podido con todos los programas, en este estoy mas que atascado, el problema es el siguiente:

Realizar una calculadora con sockets. El cliente envia 2 numeros enteros de 2 bytes cada uno mas el simbolo de la operacion (+, - , / , *) de 1 byte, el mensaje tendria que ser asi "35003500-" . De este lado hay cosas que no entiendo, a que se refiere con un entero de 2 bytes, segun yo es -32k hasta 32k aprox pero entonces como puedo delimitar eso y a como entro y envio la informacion, el buffer debe ser char o que tipo de dato.
Mientras que el cliente recibe la cadena, la interpreta y regresa la operacion como 1 entero de 4 bytes, ahi de nuevo con los bytes

Si alguno puede ayudarme con el code o con algo estaria mas que agradecido, estoy en mi ultimo chance de pasar la materia o me cargo el año ): Hoy por mi mañana por ustedes xc

 Cliente.cpp

// IP y puerto fijos; envia y recibe un mensaje
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include<iostream>
using namespace std;
//#define PORT 8080
#define PORT 8888


int main(int argc, char const *argv[])
{
   int sock = 0, valread;
   struct sockaddr_in serv_addr;
   //char *hello = "Hello from client 1";
    char A[1024],B[1024],sign[1024]; //2 bytes 1 byte
   char buffer[1024] = {0};
   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      printf("\n Socket creation error \n");
      return -1;
   }

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_port = htons(PORT);
   
   // Convert IPv4 and IPv6 addresses from text to binary form
   if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
   {
      printf("\nInvalid address/ Address not supported \n");
      return -1;
   }

   if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
   {
      printf("\nConnection Failed \n");
      return -1;
   }

    cout<<"Entero A:"<<endl;
    cin>>A;
    cout<<"Entero B:"<<endl;
    cin>>B;
    cout<<"Signo:"<<endl;
    cin>>sign;

    //cast bitwise
   send(sock , A , 1024 , 0 );
    send(sock , B , 1024 , 0 );
    send(sock, sign , 1024 , 0);
   printf("Numbers sent!\n");

   //valread = read( sock , buffer, 1024);
   //printf("%s\n",buffer );
   return 0;
}

    Servidor.cpp

// Server side C/C++ program to demonstrate Socket programming
// El servidor recibe y luego envia un mensaje

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include<iostream>
using namespace std;
#define PORT 8888

//Caracteristicas: puerto fijo TCP
int main(int argc, char const *argv[])
{
   int server_fd, new_socket, valread;
   struct sockaddr_in address;
   int opt = 1;
   int addrlen = sizeof(address);
   char buffer[1024] = {0};
   
   // Creating socket file descriptor
   if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
   {
      perror("socket failed");
      exit(EXIT_FAILURE);
   }
   
   // Forcefully attaching socket to the port 8080
   if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
                                    &opt, sizeof(opt)))
   {
      perror("setsockopt");
      exit(EXIT_FAILURE);
   }
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
   address.sin_port = htons( PORT );
   
   // Forcefully attaching socket to the port 8080
   if (bind(server_fd, (struct sockaddr *)&address,
                        sizeof(address))<0)
   {
      perror("bind failed");
      exit(EXIT_FAILURE);
   }
   if (listen(server_fd, 3) < 0)
   {
      perror("listen");
      exit(EXIT_FAILURE);
   }

    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
               (socklen_t*)&addrlen))<0)
   {
      perror("accept");
      exit(EXIT_FAILURE);
   }


    while(1){
       
   valread = read( new_socket , buffer, 1024 );
   printf("%s\n",buffer );

   //send(new_socket , hello , strlen(hello) , 0 );
   //printf("Hello message sent\n");

    }


   
   return 0;
}


En línea

_TTFH_3500

Desconectado Desconectado

Mensajes: 123



Ver Perfil
Re: Programa de Calculadora con sockets
« Respuesta #1 en: 31 Agosto 2022, 19:33 pm »

Un entero de 16 bits puede almacenar los valores entre -32768 y 32767, lo más sencillo es utilizar stdint.h
Ejemplo:
Código
  1. #include <stdint.h>
  2. int16_t entero_16bits = 12345;
Ver:
https://cplusplus.com/reference/cstdint/

Otra manera es con un arreglo de bytes:
Código
  1. // Advertencia: puede no funcionar para valores negativos
  2. int valor = 12345;
  3. unsigned char data[2];
  4. data[0] = valor & 0xFF;
  5. data[1] = (valor >> 8) & 0xFF;
  6. // El valor quedo guardado en data y ocupa 2 bytes
  7.  
  8. int recuperar_valor = data[0] | data[1] << 8;


En línea

RayR

Desconectado Desconectado

Mensajes: 243


Ver Perfil
Re: Programa de Calculadora con sockets
« Respuesta #2 en: 1 Septiembre 2022, 02:03 am »

Como te están especificando que deben ser enteros de 2 bytes, entonces supongo que te piden que envíes los datos, no como una cadena ASCII (pues en ese caso cada entero podría ocupar hasta 6 bytes, incluyendo el signo positivo/negativo) sino como valores binarios, por lo que no deberías leerlos como cadenas, sino como enteros. Así que, para empezar, A y B deberían ser de tipo int16_t, como ya te dijeron. Y no tiene ningún sentido que sign sea un array de 1024 caracteres; debería ser un simple char.

La forma más simple es enviar (y recibir) una variable a la vez. Esto no es muy eficiente ni correcto, pero te puede sacar del apuro.

En el cliente, una vez que el usuario introdujo los números y el signo, haz algo así:

Código
  1. // Conviertes de orden de bytes local a red
  2. A = htons(A);
  3. B = htons(B);
  4.  
  5. send(sock , &A , sizeof(A) , 0 );
  6. send(sock , &B , sizeof(B) , 0 );
  7. send(sock, &sign , sizeof(sign) , 0);
  8.  
  9. int32_t total;
  10. read( sock , &total, sizeof(total));
  11.  
  12. // Conviertes de orden de bytes de red a local
  13. total = ntohl(total);
  14. std::cout <<  "El total es: " << total << "\n";

En el servidor:

Código
  1. // Pesimos nombres de variables, pero por consistencia con tu codigo, los dejo asi
  2. int16_t A, B;
  3. char sign;
  4. int32_t total;
  5. read( new_socket , &A, sizeof(A) );
  6. A = ntohs(A);
  7. // ...y lo mismo para B y sign...

 Y con un switch/case verificas sign. Por ejemplo:

Código
  1. ...
  2. case '+':
  3. total = A + B;
  4. break;
  5. case '-':
  6. total = A - B;
  7. break;
  8. // etc.

Y finalmente:

Código
  1. total = htonl(total);
  2. send(new_socket , &total, sizeof(total) , 0 );

Esto, como te dije, no es ni mucho menos ideal. Dado que estás enviando cantidades diminutas de bytes, puedes dar por hecho que va a funcionar sin problemas, pero en general, sería más eficiente juntar las variables en un bloque de bytes (ojo, no cadena de texto sino bytes) y enviar/recibir eso. Y lo correcto sería verificar que los datos se envíen/reciban completos. Las funciones read y send no necesariamente envian/reciben el número de bytes que les indiques, por lo que podría ser necesario leer o enviar los restantes con llamadas sucesivas. El problema es que, viendo que buena parte de tu código simplemente la copiaste de algún lugar, y que tienes cosas inexplicables, como lo de la variable sign que te comenté al inicio, creo que la forma más correcta se te podría complicar. De cualquier manera, te doy algunas sugerencias por si lo quisieras intentar.

Dado que vas a enviar 5 bytes fijos, podrías hacer algo así en el cliente:

Código
  1. // Como NO es una cadena, no necesita caracter nulo al final
  2. char buffer[5];
  3. /* Igual podriamos redondear a 8 chars, pues las potencias de 2 siempre son mucho mas agradables :) */

Y copiar ahí los valores de A, B (luego de haberlos convertido con htons) y sign. Para esto podrías usar memcpy, u operaciones a nivel de bits, como &, >> (si ya estás en programación de sockets, supongo que ya conocerás el funcionamiento de memcpy al menos).

Luego envias ese buffer.

Las funciones send y read devuelven el número de bytes leídos/enviados, así que puedes tener una variable que lleve la cuenta de los bytes que faltan de enviar/leer. Aquí va un pseudocódigo con una forma típica de enviar buffers completos:

Código
  1. int restantes = TOTAL_A_ENVIAR;
  2. while (restantes > 0) {
  3. int enviados = send(bytes_restantes_del_buffer);
  4. /* verificar el valor de enviados: si es igual a 0 o -1, algo salio mal. Lidiar con el error */
  5. // En caso contrario
  6. restantes -= enviados;
  7. }

Lo mismo al recibir datos con read. Una vez leído el buffer, se copian sus 2 primeros bytes a A, y los dos siguientes a B (de nuevo, se puede hacer con memcpy), y  luego las conviertes a representación local con ntohs. En el caso de sign, dado que es un char, directamente le podrías asignar el valor de buffer[4].
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[Perl](Calculadora) Mi primer programa
Scripting
Niko^ 1 4,458 Último mensaje 13 Diciembre 2010, 08:18 am
por leogtz
mi primer programa en asm calculadora muy basica :3
ASM
daryo 1 5,019 Último mensaje 26 Junio 2014, 05:01 am
por Vaagish
guardar un numero y mostrarlo de nuevo programa calculadora
.NET (C#, VB.NET, ASP)
creiko 1 3,294 Último mensaje 25 Agosto 2016, 18:49 pm
por Eleкtro
programa de una calculadora en c++
Programación C/C++
Ceykhann 1 2,058 Último mensaje 8 Enero 2017, 03:25 am
por Ceykhann
Programa C# Principiantes - Calculadora de IMC
.NET (C#, VB.NET, ASP)
CarlCC 0 11,139 Último mensaje 17 Enero 2017, 04:06 am
por CarlCC
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines