1:udp通信框图
在上面的客户端,也是可以执行bind()和connect操作的,在下面的客户端代码中,我们是这么来实现的。
2:udp server端代码
#if 1
#include "./../../udp_client/src/iolib/iolib.h" /* 添加用户自已的I/O函数库 */
#define MAX_LINE 100
//extern int checkSelect(int handfd,char *rwflag);
void my_fun(char * p)
{
if(p == NULL) /* 空串 */
return;
for (; *p != '\0'; p++)
if(*p >= 'A'&& *p <= 'Z')
*p = *p -'A'+ 'a';
}
int getUdpServerSocketId(int argc, char *argv[])
{
struct sockaddr_in servaddr;
int sockfd;
if (argc != 3)
{
fputs("usage: ./client serverIp serverPort\n", stderr);
exit(1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd == -1)
{
perror("create udp socket....\n");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &servaddr.sin_addr.s_addr);
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
{
printf("set ip address error!\n");
exit(0);
}
if(bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1)
{
perror("call to bind");
exit(1);
}
return sockfd;
}
int main(int argc, char *argv[])
{
struct sockaddr_in clientaddr;
int s_fd,i=0,found=0;;
socklen_t addr_len,sndAddrLen;
char buf[MAX_LINE];
char addr_p[INET_ADDRSTRLEN];
int n;
s_fd = getUdpServerSocketId(argc,argv);
while (1)
{
memset(buf,0,MAX_LINE);
sndAddrLen = addr_len = sizeof(clientaddr);
n = recvfrom(s_fd, buf, MAX_LINE, 0, (struct sockaddr *) &clientaddr, &addr_len);
if (n == -1)
{
perror("fail to receive\n");
exit(1);
}
else
{
printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &clientaddr.sin_addr, addr_p, sizeof(addr_p)),ntohs(clientaddr.sin_port));
printf("content is :len:%d %s\n",n, buf);
my_fun(buf);
while(i++<5)
{
n = sendto(s_fd, buf, n, 0, (struct sockaddr *) &clientaddr, sndAddrLen);
if (n == -1)
{
perror("fail to send\n");
exit(1);
}
sleep(2);
}
i=0;
}
}
if(close(s_fd) == -1)
{
perror("fail to close");
exit(1);
}
return 0;
}
#endif
3:udp client端代码
#include "./iolib/iolib.h" /* 添加用户自已的I/O函数库 */
#define MAX_LINE 80
int getUdpClietnSocketId(int argc, char *argv[])
{
struct sockaddr_in servaddr,clientaddr;
int sockfd;
#if 0
if (argc != 4)
{
fputs("usage: ./client serverIp serverPort localIp\n", stderr);
exit(1);
}
#endif
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd == -1)
{
perror("create udp socket....\n");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &servaddr.sin_addr.s_addr);
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
{
printf("set ip address error!\n");
exit(0);
}
#if 1
if(argv[3]!=NULL)
{
perror("bind");
bzero(&clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[3], &clientaddr.sin_addr.s_addr);
if(inet_pton(AF_INET, argv[3], &clientaddr.sin_addr) <= 0)
{
printf("set ip address error!\n");
exit(0);
}
if (bind(sockfd, (struct sockaddr *) &clientaddr, sizeof(struct sockaddr_in)) == -1)
{
perror("udp bind......");
}
}
#endif
//inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr.s_addr);
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))==-1)
{
perror("udp connect....");
exit(0);
}
return sockfd;
}
int main(int argc, char *argv[])
{
int s_fd,len,count=0;
char buf[MAX_LINE];
char rcvbuf[MAX_LINE];
memset(buf,0,MAX_LINE);
s_fd = getUdpClietnSocketId(argc,argv);
while(1)
{
if(checkSelect(STDIN_FILENO,"r")==0)
{
memset(buf,0,MAX_LINE);
#if 1
if(fgets(buf,MAX_LINE,stdin)!=NULL)
{
/*fgets()会在结尾将换行符'\n'读入到缓冲区,而gets()不会,因此需要将多余的\n去掉,更改为字符串结尾标识'\0'*/
buf[strlen(buf)-1]='\0';
#endif
#if 0
if(gets(buf)!=NULL)
{
#endif
if((strlen(buf)==0)||(buf[0]=='\0'))
{ // printf("send len:%d : %s\n",strlen(buf),buf);
continue;
}
len = my_write(s_fd, buf, strlen(buf)); /* 发送字符串,该串包含‘\0’结束符 */
if(len == -1) /* 写操作失败,程序退出 */
{
perror("udp write....");
exit(1);
}
else
{
printf("send len:%d : %s\n",strlen(buf),buf);
}
}
}
/* 读取服务器程序发回的串,由于是同一台主机通信,不存在延时的问题。
* 但是在真正的网络环境中,要处理读操作的延时问题。
*/
if(checkSelect(s_fd,"r")==0)
{
memset(rcvbuf,0,sizeof(rcvbuf));
while(1)
{
len = read(s_fd, rcvbuf, sizeof(rcvbuf));
if(len>0)
{
printf("recV len;%d : %s\n",len, rcvbuf); /* 打印该串 */
}
if(len == -1) /* 读失败,退出程序 */
{
exit(1);
}
break;
}
}
//printf("-------------------\n");
syslog(LOG_USER|LOG_INFO,"count: %d",count++);
}
if(close(s_fd) == -1)
{ /* 关闭套接字,结束通信 */
perror("fail to close");
exit(1);
}
return 0;
}
4:代码执行结果
其测试代码可以在:linux udp测试代码