Rieccoci
il codice che ti posto non è tanto diverso dal tuo, ci sono un po' più di controlli.
sia il client, che il server, sono parametrici.
Setto gli argomenti, e quindi le variabili, quando lancio il processo.
altrimenti se cambio porta, messaggio, o indirizzi lan, mi tocca riscrivere il codice.
Importante:
nel client ho messo un controllo sulla lunghezza del messaggio,
strlen(_argv1[3]) > BUFFERSIZE
non è necessario perchè non chiamo ne
memcpy, ne
strcpy, ma setto direttamente il puntatore
char* buffer_to_send = argv[3];
il messaggio puo' essere lungo quanto vuoi, però dovra essere minore di 65535 bytes che è la lunghezza massimo del protocollo udp, (se non ricordo male).
il controllo serve solo per avere un riscontro immediato su quello che spedisce il client e quello che riceve il server,
per evitare il caso in cui il client spedisce un buffer di 35 caratteri e il server cmq sia ne visualizza solo 30.
questo perchè nel server la recvfrom() è settata con BUFFERSIZE, e più di BUFFERSIZE non riceve.
nel server ho settato la cella numbrx del buffer con il carattere di fine stringa
recv_buf[numbrx]='\0';
questo perchè se il client spedisce prima HELLOUDP e poi spedisce ONE
la printf del server , al secondo messaggio, visualizzerà ONELOUDP perchè rimane il refuso del messaggio precedente.
si potrebbe anche resettare il buffer recv_buf con memset, ma lo sconsiglio
perchè, sempre per il discorso di prima, se vengono spediti
messaggi lunghi o a raffica la memset inizia ad avere un peso.
cosi facendo setti direttamente l'ennesimo bytes ricevuto con la '\0' carattere di fine stringa, e la printf sarà corretta.
se proprio ti vuoi leggere qualcosa
su internet c'è tanto a volte pure troppo e non si sa' dove cercare
ce ne sono milioni di testi, questo è un buon manuale che volendo in rete si trova
The Linux Programming Interface di Michael KerrisK
cmq l'esempio che hai fatto va' benissimo come inizio.
dovresti ampliarlo mettendo dei signal handler che richiamano dei thread che processano il messagio
così ricopri vari argomenti.
Se hai domande o dubbi non aver timore.
The Force May Be With You.
Client:
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 30
int in_arg_check(int _argci,char* _argv1[]){
const char* help_txt={"./udp_client (address to send) (port) \"(message)\" \n"
"ex: ./udp_client 192.168.1.5 48000 \"HELLO_UDP\" \a"};
const int num_of_arg=4; //(processname) (address to send) (port) (message)
if(_argci < num_of_arg){
printf("too few argument, how to launch: %s\n",help_txt);
return EXIT_FAILURE;
}else if(_argci > num_of_arg){
printf("too many argument, how to launch: %s\n",help_txt);
return EXIT_FAILURE;
}else if (strlen(_argv1[3]) > BUFFERSIZE){ // check lenght of message
printf("too long message less than 30 bytes or chars %d\n",strlen(_argv1[3]));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void ErrorHandler(char *errorMessage) {
printf("%s",errorMessage);
printf(" error code: %d\n",errno);
printf(" error string: %s\n",strerror(errno));
}
int main(int argc,char* argv[]){
if(EXIT_FAILURE == in_arg_check(argc,argv))
return EXIT_FAILURE;
int sock;
struct sockaddr_in ServerAddr;
// set udp param
char* addrip_server = argv[1]; // address server ip
uint16_t remote_port = atoi(argv[2]); // remote port
char* buffer_to_send = argv[3]; // buffer to sent
size_t lenght_msg = strlen(buffer_to_send);
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sock < 0){
ErrorHandler("Errore inizializzazione socket()\n");
return EXIT_FAILURE;
}
memset(&ServerAddr, 0, sizeof(ServerAddr));
ServerAddr.sin_family = PF_INET;
ServerAddr.sin_port = htons(remote_port);
ServerAddr.sin_addr.s_addr = inet_addr(addrip_server);
int sent_bytes = sendto(sock,buffer_to_send,lenght_msg,0,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr));
if( sent_bytes < 0 ){
ErrorHandler("Errore con la sendto()\n");
return EXIT_FAILURE;
}
printf("sent message:\"%s\" num. bytes:%d \nto ---->>> address ip:%s remote port:%d\n",buffer_to_send,sent_bytes,addrip_server,remote_port);
return EXIT_SUCCESS;
}
Server:
#include <sys/types.h> // socket BSD o release minori di POSIX.1
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h> // hostent
#include <errno.h> // errno
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 30
int in_arg_check(int _argci,char* _argv1[]){
const char* help_txt={"./udp_server (port) \a\n"
"ex: ./udp_server 48000 "};
const int num_of_arg=2; //(processname) (address to send) (port) (message)
if(_argci < num_of_arg){
printf("too few argument, how to launch: %s\n",help_txt);
return EXIT_FAILURE;
}else if( _argci > num_of_arg){
printf("too many argument, how to launch: %s\n",help_txt);
return EXIT_FAILURE;
}
printf("set local port: %s\n",_argv1[1]);
return EXIT_SUCCESS;
}
void ErrorHandler(char *errorMessage) {
printf("%s",errorMessage);
printf(" error code: %d\n",errno);
printf(" error string: %s\n",strerror(errno));
}
int main(int argc,char* argv[]){
if(EXIT_FAILURE == in_arg_check(argc,argv))
return EXIT_FAILURE;
struct sockaddr_in ServerAddr;
struct sockaddr_in ClientAddr;
// set udp param
uint16_t local_port = atoi(argv[1]); // local port
unsigned int ClientAddrLen = sizeof(ClientAddr);
char recv_buf[BUFFERSIZE];
memset(&ServerAddr, 0, sizeof(struct sockaddr_in));
memset(&ClientAddr, 0, sizeof(struct sockaddr_in));
memset(recv_buf, 0, sizeof(recv_buf));
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sock < 0){
ErrorHandler("Errore inizializzazione socket()\n");
return EXIT_FAILURE;
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(local_port);
ServerAddr.sin_addr.s_addr = INADDR_ANY;
int ret_bind = bind(sock,(struct sockaddr *) &ServerAddr, sizeof(ServerAddr));
if(ret_bind < 0){
ErrorHandler("Error bind()\n");
return EXIT_FAILURE;
}
while(1){
printf("wait message from client...\n");
ssize_t numbrx = recvfrom(sock, recv_buf, BUFFERSIZE, 0,
(struct sockaddr*)&ClientAddr, &ClientAddrLen);
if(numbrx <= 0){
ErrorHandler("Error recvfrom()\n");
return EXIT_FAILURE;
}
printf("received bytes :%lu\n",numbrx);
recv_buf[numbrx]='\0'; // truncate buffer at current bytes received to delete previous message
printf("received message: \"%s\"\n",recv_buf);
for(int i=0; i<numbrx; i++){
if( recv_buf[i]=='a' || recv_buf[i]=='e' || recv_buf[i]=='i' || recv_buf[i]=='o' || recv_buf[i]=='u' ||
recv_buf[i]=='A' || recv_buf[i]=='E' || recv_buf[i]=='I' || recv_buf[i]=='O' || recv_buf[i]=='U'){
recv_buf[i]=' ';
}
}
printf("modify message: \"%s\"\n", recv_buf);
struct hostent* client = gethostbyaddr((char *)&ClientAddr.sin_addr.s_addr,sizeof(struct in_addr), PF_INET);
if ( client != NULL ){
printf("client name: %s\n\n",client->h_name);
}
else{
ErrorHandler("Error gethostbyaddr()\n");
return EXIT_SUCCESS;
}
}
}