需要实现的功能要点如下:
1)通过对等模式实现通信。
2)因为UDP的程序是通过send和recv交替运行的,需要注意阻塞问题。通过Setsockopt,设置阻塞时间;设置read/recv为非阻塞模式。
3)设初值为1,每次+1,直至增加到n。
详细代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/******************************** Locals ************************************/
int iUdpSockfd; // define server sockfd
static int iIplength = 15; // IP address length
const int iMax = 10; // set the max number
/******************************** Code **************************************/
/*****************************************************************************
* Function : KillHandle
* Description: receive the ctrl+c, and close the parent's socket and exit proc
* Parameter :
* Return : void
* Explain : NO
******************************************************************************/
void KillHandle()
{
close (iUdpSockfd);
printf("%d kill me (SIGINT,SIGTERM).\n", getpid());
exit (0);
}
/******************************************************************************
* Function : main
* Description : work as server: receive a number, send number++
* Parameter : IN int arg:
* number of parameters in command line
* char * argv[]:
* First address of the string in command line
* char ** evniron:
* Environment variable
* Return : The operation result.
* 0 : run and exit normally.
* !0 : run adn exit abnormally.
* Explain : use UDP socket 一个程序完成stUdpAddress和stUdpAddress2 之间的收发,
只要只命令行出入命令的时候开两个终端,将对方的端口号和自己的端口号调换就行了。
******************************************************************************/
int main(int arg, char * argv[], char ** evniron)
{
struct sockaddr_in stUdpAddress; // self addr struct
struct sockaddr_in stUdpAddress2; // other addr struct
char cIpaddrSelf[iIplength+1] ; // self IP addr
char cIpaddrOther[iIplength+1] ; // other IP addr
int iUdpLen; // these sockaddr_in length
int iPort1 = 9734; // default selfport value
int iPort2 = 9735; // default other value
int iExit = 1; // exit identifier
int iReturn = 0; // record some function return
int i = 1; // init value
int iError = 0; // record the times of failing to recvfrom()
struct timeval stRecvto; // define a time struct for set setsockopt()
int iTolen = sizeof(struct timeval);
stRecvto.tv_sec = 3; // wait time
stRecvto.tv_usec = 0;
// initialise char array
memset(cIpaddrSelf, '\0', sizeof(cIpaddrSelf ));
memset(cIpaddrOther, '\0', sizeof(cIpaddrOther));
// initialise it's original value is "127.0.0.1"
strcpy(cIpaddrSelf, "127.0.0.1");
strcpy(cIpaddrOther, "127.0.0.1");
printf("--------------------- UDP socket begin-----------------------\n\n");
// get conmand from the conmand lane
while ((iReturn = getopt(arg, argv, "p:q:a:b:")) != EOF)
{
switch (iReturn)
{
case 'p': // self port
iPort1 = atoi(optarg);//optarg 是getopt的一个参数,表示-p后个那个命令行参数放到iPort1中
break;
case 'q': // other port
iPort2 = atoi(optarg);
break;
/* case 'a': // self IP address
strcpy(cIpaddrSelf, optarg);
break;*/
case 'b': // other Ip address
strcpy(cIpaddrOther, optarg);
break;
default:
perror("error comand!\n");
perror("it will use the default value!\n");
break;
}
}
//printf(" selfport = %5d, self IP = %s.\n", iPort1, cIpaddrSelf );
printf("otherport = %5d, other IP = %s.\n", iPort2, cIpaddrOther);
// create UDP socket
iUdpSockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == iUdpSockfd)
{
perror("create socket failed!\n");
exit(1);
}
//initalize socket struct: self;
stUdpAddress.sin_family = AF_INET;
stUdpAddress.sin_addr.s_addr = inet_addr(cIpaddrSelf); // IP
stUdpAddress.sin_port = htons(iPort1); // port
//initalize socket struct: other;
stUdpAddress2.sin_family = AF_INET;
stUdpAddress2.sin_addr.s_addr = inet_addr(cIpaddrOther); // IP
stUdpAddress2.sin_port = htons(iPort2); // port
iUdpLen = sizeof(stUdpAddress);
// when press ^c, it will emit SIGINT;
signal(SIGINT, KillHandle);
// bind the iUdpSockfd to the stUdpAddress
if (-1 == bind(iUdpSockfd, (struct sockaddr *)&stUdpAddress, iUdpLen))
{
perror("bind failed!\n");
close (iUdpSockfd);
exit (1);
}
// set the function: recvfrom() waiting time
setsockopt(iUdpSockfd, SOL_SOCKET, SO_RCVTIMEO, &stRecvto, iTolen);
while (i < iMax)
{
// send i to stUdpAddress2
iReturn = sendto(iUdpSockfd, &i, sizeof(i), 0,
(struct sockaddr *) &stUdpAddress2, sizeof(stUdpAddress2));
if (-1 == iReturn)
{
perror("sendto failed!\n");
break;
}
sleep(1);
// receive i from stUdpAddress
iReturn = recvfrom(iUdpSockfd, &i, sizeof(i), 0,
(struct sockaddr *) &stUdpAddress, &iUdpLen);
i++;
if (iReturn != -1)
{
printf("received i = %d.\n", i);
}
else
{
break;
}
}
if (i == iMax)
{
printf("--------------------successful transfer!---------------------\n");
}
else
{
printf("-----------------error happened in transfer!-----------------\n");
}
// close the UPD socket
iReturn = close(iUdpSockfd);
if (-1 == iReturn)
{
perror("Fail to close socket.\n");
exit(1);
}
exit(0);
}