网络编程UDP的socket编程实现(linux下)
一、UDP的编程步骤:
1、服务器端:
socket()->bind()->recvfrom()->sendto()->close()
2、客户端:
socket()->sendto()->recvfrom()->close()
二、主要的API
1、sendto()函数的使用
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void * buf, size_t len , int flags, const struct sockaddr * dest_addr , socklen_t addrlen);
(1)功能:向指定的数据接收端发送指定的数据。
(2)返回值:成功,返回实际发送的字节数。失败,返回-1.
(3)参数:
----sockfd:发送操作使用的套接字文件描述符
-----buf:要发送的数据在内存中的首地址
-----len:要发送的数据的长度
------flags:发送标志,一般为0
------dest_addr:数据接收端的地址(包含IP地址和端口号)的结构体指针
-------addrlen:数据接收端地址结构体的大小
2、recvfrom()函数的使用
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void * buf , size_t len , int flags , struct sockaddr * src_addr, socklen_t * addrlen);
(1)功能:接收数据发送端到达的数据
(2)返回值:成功,返回实际接收到的字节数。失败返回-1
(3)参数:
-----sockfd:接收操作使用的套接字文件描述符
-----buf:接收到的数据存放在内存中的位置
------len:指buf缓冲区的大小,即期望接收的最大数据的长度
-----flags:接收标志,一般为0
-----src_addr:指向的结构体将被数据发送端的地址(含IP地址和端口号)所填充
-----addrlen:所指向的存储位置,调用前应填入src_addr和addrlen的结构体大小,调用后则将被填入发送端的地址的实际大小
备注:若不需要发送端的IP地址和端口号,可以将src_addr和addrlen都设置为NULL
三、示例:
服务器端代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <error.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#define SERVER_PORT 8888
#define MAX_MSG_SIZE 1024
void udps_respon(int sockfd)
{
struct sockaddr_in addr;
int n,i;
unsigned int addrlen;
char msg[MAX_MSG_SIZE];
while(1)
{
n = recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr *)&addr,&addrlen);
msg[n]=0;
fprintf(stdout,"I have received %s",msg);
n=strlen(msg);
for(i=0;i<n;i++)
{
msg[i] = toupper(msg[i]);
}
sendto(sockfd,msg,n,0,(struct sockaddr *)&addr,addrlen);
}
}
int main()
{
int sockfd;
struct sockaddr_in addr;
sockfd = socket(AF_INET,SOCK_DGRAM,0);
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
if( bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in) )<0 )
{
perror("bind");
exit(1);
}
udps_respon(sockfd);
close(sockfd);
return 0;
}
客户端代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define MAX_BUF_SIZE 1024
void udpc_requ(int sockfd,const struct sockaddr_in * addr,int len)
{//
char buffer[MAX_BUF_SIZE];
int n;
while(1)
{
fgets(buffer,MAX_BUF_SIZE,stdin);
sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr *)addr,len);
printf("I have sent to server %s",buffer);
printf("Waiting respond from server\n");
bzero(buffer,MAX_BUF_SIZE);
n=recvfrom(sockfd,buffer,MAX_BUF_SIZE,0,NULL,NULL);
buffer[n]=0;
printf("I have received from server..");
fputs(buffer,stdout);
printf("\n");
}
}
int main(int argc,char ** argv)
{
int sockfd,port;
struct sockaddr_in addr;
if(argc != 3 )
{
fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]);
exit(1);
}
if((port = atoi(argv[2]) )< 0)
{
fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]);
exit(1);
}
sockfd = socket(AF_INET,SOCK_DGRAM,0);
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if(inet_aton(argv[1],&addr.sin_addr) < 0)
{
fprintf(stderr,"IP error:%s\n",strerror(errno));
exit(1);
}
udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in));
close(sockfd);
return 0;
}
运行结果:
服务器端:
[root@rac2 ~]# ./udpServer
I have received abc
I have received zhandan
客户端:
[root@rac2 ~]# ./udpClient 127.0.0.1 8888
abc
I have sent to server abc
Waiting respond from server
I have received from server..ABC
zhandan
I have sent to server zhandan
Waiting respond from server
I have received from server..ZHANDAN