Author: WhoAmI
Date: 20220726
Copyright: CC BY-NC-SA
/*
20190225
udps.c
Author:WhoAmI
UDP client/server
maximum transmission unit (MTU):
Please see https://en.wikipedia.org/wiki/Maximum_transmission_unit
TTL problems:
void setttl(int sock, uint8_t ttl)
{
int ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(uint8_t));
if (ret != 0)
printf("Failed to setsockopt(): %s\n", strerror(errno));
}
IP fragmentation (特別經過 VPN):
Please see https://en.wikipedia.org/wiki/IP_fragmentation
Route problems
*/
udps.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
/*******************************/
/* FIXME */
/* MTU */
/*******************************/
#define MAXMTU 2500
/*******************************/
#define PANIC(msg) { perror(msg); exit(EXIT_FAILURE); }
#define STDIN 0
#define TIMEOUT 10
#define READSIZE 512
#define DEFAULT_PORT 9999
#define DEFAULT_CPORT 9990
static void hander(int sig)
{
printf("sig=%d\n",sig);
}
static ssize_t dump_frame(int fd, const void *buf,size_t len,int flags,const struct sockaddr *dest_addr, socklen_t addrlen)
{
ssize_t n;
int mode=0;
n=0;
if(mode==0)
{
n=sendto(fd,buf,len,flags,dest_addr,addrlen);
// n=write(fd,buf,count);
}
return n;
}
static ssize_t forward_frame(int fd, const void *buf,size_t len,int flags,const struct sockaddr *dest_addr, socklen_t addrlen)
{
/*
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
*/
ssize_t n;
int mode=0;
n=0;
if(mode==0)
{
n=sendto(fd,buf,len,flags,dest_addr,addrlen);
}
return n;
}
#define DEFAULTIP "127.0.0.1"
int udp_client(int _port,int _rport, char *ip, int secs)
{
int server_fd;
int remote_port;
ssize_t recvbytes;
char rbuf[MAXMTU];
struct sockaddr_in server_addr;
struct sockaddr_in remote_addr,client_addr;
char *remote_ip=DEFAULTIP;
fd_set master_fds;
fd_set read_fds;
int fdmax;
struct timeval tv;
int port;
int len;
int i, j;
char buf[READSIZE],ch;
int nbytes;
int yes=1;
int retval;
int connections=0;
port=DEFAULT_CPORT;
if(_port>0)port=_port;
remote_port=9999;
if(_rport>0)remote_port=_rport;
if(ip!=NULL)remote_ip=ip;
signal(SIGPIPE,hander);
FD_ZERO(&master_fds);
FD_ZERO(&read_fds);
/* UDP SOCK_DGRAM */
if ((server_fd = socket(AF_INET, SOCK_DGRAM , 0)) == -1) PANIC("socket");
if (setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) PANIC("setsockopt");
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) PANIC("bind");
FD_SET(server_fd,&master_fds);
FD_SET(STDIN,&master_fds); //read from STDIN
fdmax = server_fd;
connections=0;
/* in_addr_t inet_addr(const char *cp);*/
//clean remote_addr and set values
memset(&remote_addr,0,sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr.s_addr = inet_addr(remote_ip);;
remote_addr.sin_port = htons(remote_port);
// Server Loop
for(;;)
{
tv.tv_sec = secs;
tv.tv_usec = 0;
read_fds=master_fds;
retval = select(fdmax+1,&read_fds,NULL,NULL,&tv);
switch(retval)
{
case -1:
perror("select");
break;
case 0:
printf("C:Time Out...\n");
default:
if (FD_ISSET(server_fd,&read_fds))
{
/*
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
Please see man page
*/
printf("C:Recv from %d\n",server_fd);
memset((struct sockaddr_in *)&client_addr,0,sizeof(client_addr));
len=sizeof(client_addr);
if ((recvbytes=recvfrom(server_fd,rbuf, MAXMTU,0,(struct sockaddr *)&client_addr,&len)) == -1)
{
perror("recvfrom");
continue;
}
else
{
printf("C:New frame from %s on socket %d, connection=%d\n",inet_ntoa(client_addr.sin_addr),server_fd,connections);
write(1,rbuf,recvbytes);//FIXME write to stdout
}
}
;
break;
}//switch
printf("\nInput bytes:>\n");
if ((nbytes=read(0, buf, sizeof(buf))) > 0) //FIXME: we can read from stdin
{
for(j=server_fd; j<=fdmax; j++)
{
if (FD_ISSET(j, &master_fds))
{
printf("C:Forward %d bytes to %d\n",nbytes,j);
if (forward_frame(j, buf, nbytes, 0,(const struct sockaddr *)&remote_addr,sizeof(remote_addr)) == -1)
{
printf("socket fd=%d",j);
perror("send");
}
}
}//for
}
}//for server loop
return 0;
}
static ssize_t readln(int sockfd, char *buf,size_t len, int time_out)
{
int n;
fd_set readfds;
struct timeval tval;
ssize_t total;
int ret;
char *pc;
total=0;
FD_ZERO(&readfds);
do
{
FD_SET(sockfd, &readfds);
tval.tv_sec = time_out;
tval.tv_usec = 0;
if(time_out<=0)
{
if(( n = select(sockfd+1, &readfds, NULL, NULL, NULL))<0)return -1;
}
else
{
if ( (n = select(sockfd+1, &readfds, NULL, NULL, time_out ? &tval : NULL)) == 0)
{
errno = ETIMEDOUT;
printf("Read timeout!\n");
return(-1);
}
}
ret=read(sockfd,buf+total,1); //Notice that '\n'
pc= buf+total;
if(ret>0)
{
total+=ret;
if(*pc=='\n')break;
}
else if(ret==0)
{
//eof
break;
}
else
{
return -1;
}
}
while(total<len);
if(total<len)buf[total]=0;
else buf[len-1]=0;
return total;
}
int main_server(int _port, int secs,int echo)
{
int server_fd;
int client_fd;
ssize_t recvbytes;
char rbuf[MAXMTU];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
fd_set master_fds;
fd_set read_fds;
int fdmax;
struct timeval tv;
int port;
int len;
int i, j;
char buf[READSIZE],ch;
int nbytes;
int yes=1;
int retval;
int connections=0;
int READIN=0;
port=DEFAULT_PORT;
if(_port>0)port=_port;
signal(SIGPIPE,hander);
FD_ZERO(&master_fds);
FD_ZERO(&read_fds);
/* UDP SOCK_DGRAM */
if ((server_fd = socket(AF_INET, SOCK_DGRAM , 0)) == -1) PANIC("socket");
if (setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) PANIC("setsockopt");
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) PANIC("bind");
#ifdef TCPSERVER
if (listen(server_fd,10) == -1) PANIC("listen");
#endif
FD_SET(server_fd,&master_fds);
// FD_SET(STDIN,&master_fds); //read from STDIN
fdmax = server_fd;
connections=0;
// Server Loop
for(;;)
{
tv.tv_sec =secs;
tv.tv_usec = 0;
read_fds=master_fds;
fprintf(stderr,"S:Wait...%d secs\n",secs);
retval = select(fdmax+1,&read_fds,NULL,NULL,&tv);
switch(retval)
{
case -1:
perror("select");
break;
case 0:
fprintf(stderr,"S:Time Out...\n");
default:
//20190224 BUG FIXED!
for(i=server_fd; i<= fdmax; i++)
{
if (FD_ISSET(i,&read_fds))
{
/*
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
*/
memset((struct sockaddr_in *)&client_addr,0,sizeof(client_addr));
len=sizeof(client_addr);
if ((recvbytes=recvfrom(server_fd,rbuf, MAXMTU,0,(struct sockaddr *)&client_addr,&len)) == -1)
{
perror("recvfrom");
continue;
}
else
{
fprintf(stderr,"S:New frame from %s:%d on socket %d, connection=%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),server_fd,connections);
//echo
len=sizeof(client_addr);
if( echo){
dump_frame(server_fd,rbuf,recvbytes,0,(struct sockaddr *)&client_addr,len);//FIXME
}
write(1,rbuf,recvbytes);
}
}
}
// exit(0);
break;
}//switch
if(READIN==1)
{
printf("S:Read from stdin...10 secs>\n");
if ((nbytes=readln(0, buf, sizeof(buf),10)) > 0) //FIXME: we can read from stdin
{
for(j=server_fd; j<=fdmax; j++)
{
if (FD_ISSET(j, &master_fds))
{
printf("S:Send %d bytes to others...",nbytes);
if (forward_frame(j, buf, nbytes, 0,(const struct sockaddr *)&client_addr,sizeof(client_addr)) == -1)
{
perror("send");
}
}
}//for
}
}//read from stdin
}//for server loop
return 0;
}
int main(int argc, char *argv[])
{
int port=DEFAULT_PORT;
int mode=0; //default: server
int i;
char *ip="127.0.0.1";
int rport=DEFAULT_PORT; //remort port
int lport=DEFAULT_PORT-10; //remort port
int timeout=TIMEOUT;
int ret;
int echo=0;
if(argc>1)
{
for(i=1;i<argc;i++)
{
if(strcmp(argv[i],"-t")==0)
{
i++;
timeout=atoi(argv[i]);
}
if(strcmp(argv[i],"-c")==0)
{
mode=1; //client
}
if(strcmp(argv[i],"-s")==0)
{
mode=atoi(argv[++i]); //server
printf("mode=%d\n",mode);
}
if(strcmp(argv[i],"-ip")==0)
{
ip=argv[++i];
}
if(strcmp(argv[i],"-rport")==0)
{
rport=atoi(argv[++i]);
}
if(strcmp(argv[i],"-port")==0)
{
port=atoi(argv[++i]);
lport=port;
}
if(strcmp(argv[i],"-echo")==0)
{
echo=1;
printf("Echo on!\n");
}
}
}
else
{
printf("Usage:\n%s [-c] [-s 1] [-ip 127.0.0.1] [-rport 9999] [-port 9999] [-t 60]\n\n",argv[0]);
printf("default: %s -s %d -ip %s -rport %d -port %d -t %d\n",argv[0],mode,ip,rport,port,timeout);
}
if(mode==0)
{
printf("Server start on UDP port %d...\n",port);
ret=main_server(port, timeout,echo);
}
if(mode==1)
{
printf("Client start on port %d...remort ip=%s port=%d\n",lport, ip,rport);
//int udp_client(int _port,int _rport, char *ip, int secs)
ret=udp_client(lport,rport,ip, timeout);
}
}
Authors: CrazyDog, CrazyMonkeyemail: kccddb@gmail.comDate: 20230222
Mar 14, 2025Author: \mathcal{CrazyDog}, Ph.D. in Electrical Engineering, NCTUemail: kccddb@gmail.comDate: 20230910
Nov 4, 2024Author: WhoAmI Date: 20230523 email:kccddb@gmail.com Copyright: CC BY-NC-SA 《荀子‧勸學》不積跬步,無以至千里;不積小流,無以成江海。 I. Mutex variables MUST be declared with type pthread_mutex_t, and must be initialized before they can be used. II. 了解 pthread_mutex_lock / pthread_mutex_unlock 與可能問題和代價 III. 程式執行效率與startvation 等問題
Jul 11, 2024Author: WhoAmIemail: kccddb@gmail.com
Dec 6, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up