linux网络编程-UDP套接字编程典型模型
linux网络编程-UDP套接字通信实验,注意和上一篇文章的区分(TCP编程)
代码分析 client.c
程序分析client.c
//client.c
//
// UDP 套接字编程典型模型
//
// 客户端 服务器端
// 创建套接字(socket) 创建套接字(socket)
// 绑定服务器地址和端口(bind)
// 客户端发送请求(sendto) ----> 接收客户端请求(recvfrom)
// 客户端接收响应(recvfrom)<---- 回送响应(sendto)
// 关闭套接字(close)
//man 7 socket
//accept() , bind() , connect() , getsockname() , getsockopt() ,
//listen() , recv() , recvfrom() , recvmsg() , send() , sendmsg() ,
//sendto() , setsockopt() , shutdown() , socket() , socketpair()
//
//socket - create an endpoint for communication
//#include <sys/socket.h>
//int socket(int domain, int type, int protocol);
//RETURN VALUE
//Upon successful completion, socket() shall return a non-negative
//integer, the socket file descriptor. Otherwise, a value of -1
//shall be returned and errno set to indicate the error.
//
//bind - bind a name to a socket
//#include <sys/socket.h>
//int bind(int socket, const struct sockaddr *address,
// socklen_t address_len);
//RETURN VALUE
//Upon successful completion, bind() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//listen - listen for socket connections and limit the queue of
//incoming connections
//#include <sys/socket.h>
//int listen(int socket, int backlog);
//RETURN VALUE
//Upon successful completions, listen() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//connect - connect a socket
//#include <sys/socket.h>
//int connect(int socket, const struct sockaddr *address,
// socklen_t address_len);
//RETURN VALUE
//Upon successful completion, connect() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//accept - accept a new connection on a socket
//#include <sys/socket.h>
//int accept(int socket, struct sockaddr *restrict address,
// socklen_t *restrict address_len);
//RETURN VALUE
//Upon successful completion, accept() shall return the non-negative
//file descriptor of the accepted socket. Otherwise, -1 shall be
//returned and errno set to indicate the error.
//
//send, sendto, sentmsg - send a message on a socket
//#include <sys/socket.h>
//ssize_t send(int socket, const void *buffer, size_t length, int
//flags);
//ssize_t sendto(int socket, const void *message, size_t length,
// int flags, const struct sockaddr *dest_addr,socklen_t dest_len);
//ssize_t sendmsg(int socket, const struct msghdr *message, int
//flags);
//RETURN VALUE
//Upon successful completion, shall return the number of bytes
//sent. Otherwise, -1 shall be returned and errno set to indicate the
//error.
//
//recv, recvfrom, recvmsg - receive a message from a socket
//#include <sys/types.h>
//#include <sys/socket.h>
//ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//
//ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
// struct sockaddr *src_addr, socklen_t *addrlen);
//
//ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
//RETURN VALUE
//These calls return the number of bytes received, or -1 if an error
//occurred. The return value will be 0 when the peer has performed an
//orderly shutdown.
//
//struct iovec { /* Scatter/gather array items */
// void *iov_base; /* Starting address */
// size_t iov_len; /* Number of bytes to transfer */
//};
//
//struct msghdr {
// void *msg_name; /* optional address */
// socklen_t msg_namelen; /* size of address */
// struct iovec *msg_iov; /* scatter/gather array */
// size_t msg_iovlen; /* # elements in msg_iov */
// void *msg_control; /* ancillary data, see below */
// size_t msg_controllen; /* ancillary data buffer len */
// int msg_flags; /* flags on received message */
//};
//
//socketpair - create a pair of connected sockets
//#include <sys/socket.h>
//int socketpair(int domain, int type, int protocol,
// int socket_vector[2]);
//RETURN VALUE
//Upon successful completion, this function shall return 0;
//otherwise, -1 shall be returned and errno set to indicate the error.
//
//setsockopt - set the socket options
//#include <sys/socket.h>
//int setsockopt(int socket, int level, int option_name,
// const void *option_value, socklen_t option_len);
//RETURN VALUE
//Upon successful completion, setsockopt() shall return 0.
//Otherwise, -1 shall be returned and errno set to indicate the error.
//
//getsockopt - get the socket options
//#include <sys/socket.h>
//int getsockopt(int socket, int level, int option_name,
// void *restrict option_value, socklen_t *restrict option_len);
//RETURN VALUE
//Upon successful completion, getsockopt() shall return 0;
//otherwise, -1 shall be returned and errno set to indicate the error.
//
//getsockname - get the socket name
//#include <sys/socket.h>
//int getsockname(int socket, struct sockaddr *restrict address,
// socklen_t *restrict address_len);
//RETURN VALUE
//Upon successful completion, 0 shall be returned, the address argu‐
//ment shall point to the address of the socket, and the address_len
//argument shall point to the length of the address. Otherwise, -1
//shall be returned and errno set to indicate the error.
//
//shutdown - shut down socket send and receive operations
//#include <sys/socket.h>
//int shutdown(int socket, int how);
//how Specifies the type of shutdown. The values are as follows:
//SHUT_RD Disables further receive operations.
//SHUT_WR Disables further send operations.
//SHUT_RDWR Disables further send and receive operations.
//RETURN VALUE
//Upon successful completion, shutdown() shall return 0; otherwise,
//-1 shall be returned and errno set to indicate the error.
//
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define PORT 8000
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
struct sockaddr_in *sin_addrptr;
struct sockaddr serv_sa;
struct addrinfo *serv_aiptr, hints, *res_aiptr ;
int sockfd, res;
char buf[BUF_SIZE];
char serv_name[80];
memset(serv_name, 0, sizeof(serv_name));
strcpy(serv_name, "127.0.0.1");
if (argc > 1)
{
memset(serv_name, 0, sizeof(serv_name));
strcpy(serv_name, argv[1]);
}
//服务起地址解析函数getaddrinfo
//int getaddrinfo(const char *node, const char *service,
// const struct addrinfo *hints,
// struct addrinfo **res);
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
if((res = getaddrinfo(serv_name, NULL, &hints, &res_aiptr)) !=0)
{
fprintf(stderr, "Error getaddrinfo %s\n",gai_strerror(res));
exit(-1);
}
for(serv_aiptr = res_aiptr;serv_aiptr != NULL; serv_aiptr++)
{
if(serv_aiptr->ai_family == AF_INET)
{
serv_sa = *(serv_aiptr->ai_addr);
sin_addrptr = (struct sockaddr_in *) &serv_sa;
break;
}
}
if (serv_aiptr == NULL)
{
freeaddrinfo(res_aiptr);
printf("不能发现服务器");
exit(-1);
}
freeaddrinfo(res_aiptr);
//建立socket连接
//int socket(int domain, int type, int protocol);
//以默认协议,在INET域建立数据流套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Error socket");
exit(-1);
}
printf("套接字 ID = %d\n", sockfd);
//设置服务器sockaddr_in 结构体相关参数
sin_addrptr->sin_port = htons(PORT);
while(1)
{
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), stdin);
//发送消息到服务器端
//ssize_t sendto(int socket, const void *message,
// size_t length, int flags,
// const struct sockaddr *dest_addr,socklen_t dest_len);
if ((sendto(sockfd, buf, strlen(buf), 0, \
&serv_sa, sizeof(serv_sa))) == -1)
{
perror("Error send");
exit(-1);
}
//接收服务器端发送的消息
memset(buf, 0, sizeof(buf));
//ssize_t recvfrom(int sockfd, void *buf, size_t len,
//int flags, struct sockaddr *src_addr, socklen_t *addrlen);
if ((res = recvfrom(sockfd, buf, sizeof(buf),\
0, NULL, NULL)) == -1)
{
perror("Error recv");
exit(-1);
}
printf("接收到服务器信息:%s(%d个字节)\n", buf, res);
}
close(sockfd);
exit(0);
}
代码分析 server.c
程序分析server.c
//server.c
//
// UDP 套接字编程呢过典型模型
//
// 客户端 服务器端
// 创建套接字(socket) 创建套接字(socket)
// 绑定服务器地址和端口(bind)
// 客户端发送请求(sendto) ----> 接收客户端请求(recvfrom)
// 客户端接收响应(recvfrom)<---- 回送响应(sendto)
// 关闭套接字(close)
//man 7 socket
//accept() , bind() , connect() , getsockname() , getsockopt() ,
//listen() , recv() , recvfrom() , recvmsg() , send() , sendmsg() ,
//sendto() , setsockopt() , shutdown() , socket() , socketpair()
//
//socket - create an endpoint for communication
//#include <sys/socket.h>
//int socket(int domain, int type, int protocol);
//RETURN VALUE
//Upon successful completion, socket() shall return a non-negative
//integer, the socket file descriptor. Otherwise, a value of -1
//shall be returned and errno set to indicate the error.
//
//bind - bind a name to a socket
//#include <sys/socket.h>
//int bind(int socket, const struct sockaddr *address,
// socklen_t address_len);
//RETURN VALUE
//Upon successful completion, bind() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//listen - listen for socket connections and limit the queue of
//incoming connections
//#include <sys/socket.h>
//int listen(int socket, int backlog);
//RETURN VALUE
//Upon successful completions, listen() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//connect - connect a socket
//#include <sys/socket.h>
//int connect(int socket, const struct sockaddr *address,
// socklen_t address_len);
//RETURN VALUE
//Upon successful completion, connect() shall return 0; otherwise, -1
//shall be returned and errno set to indicate the error.
//
//accept - accept a new connection on a socket
//#include <sys/socket.h>
//int accept(int socket, struct sockaddr *restrict address,
// socklen_t *restrict address_len);
//RETURN VALUE
//Upon successful completion, accept() shall return the non-negative
//file descriptor of the accepted socket. Otherwise, -1 shall be
//returned and errno set to indicate the error.
//
//send, sendto, sentmsg - send a message on a socket
//#include <sys/socket.h>
//ssize_t send(int socket, const void *buffer, size_t length, int
//flags);
//ssize_t sendto(int socket, const void *message, size_t length,
// int flags, const struct sockaddr *dest_addr,socklen_t dest_len);
//ssize_t sendmsg(int socket, const struct msghdr *message, int
//flags);
//RETURN VALUE
//Upon successful completion, shall return the number of bytes
//sent. Otherwise, -1 shall be returned and errno set to indicate the
//error.
//
//recv, recvfrom, recvmsg - receive a message from a socket
//#include <sys/types.h>
//#include <sys/socket.h>
//ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//
//ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
// struct sockaddr *src_addr, socklen_t *addrlen);
//
//ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
//RETURN VALUE
//These calls return the number of bytes received, or -1 if an error
//occurred. The return value will be 0 when the peer has performed an
//orderly shutdown.
//
//struct iovec { /* Scatter/gather array items */
// void *iov_base; /* Starting address */
// size_t iov_len; /* Number of bytes to transfer */
//};
//
//struct msghdr {
// void *msg_name; /* optional address */
// socklen_t msg_namelen; /* size of address */
// struct iovec *msg_iov; /* scatter/gather array */
// size_t msg_iovlen; /* # elements in msg_iov */
// void *msg_control; /* ancillary data, see below */
// size_t msg_controllen; /* ancillary data buffer len */
// int msg_flags; /* flags on received message */
//};
//
//socketpair - create a pair of connected sockets
//#include <sys/socket.h>
//int socketpair(int domain, int type, int protocol,
// int socket_vector[2]);
//RETURN VALUE
//Upon successful completion, this function shall return 0;
//otherwise, -1 shall be returned and errno set to indicate the error.
//
//setsockopt - set the socket options
//#include <sys/socket.h>
//int setsockopt(int socket, int level, int option_name,
// const void *option_value, socklen_t option_len);
//RETURN VALUE
//Upon successful completion, setsockopt() shall return 0.
//Otherwise, -1 shall be returned and errno set to indicate the error.
//
//getsockopt - get the socket options
//#include <sys/socket.h>
//int getsockopt(int socket, int level, int option_name,
// void *restrict option_value, socklen_t *restrict option_len);
//RETURN VALUE
//Upon successful completion, getsockopt() shall return 0;
//otherwise, -1 shall be returned and errno set to indicate the error.
//
//getsockname - get the socket name
//#include <sys/socket.h>
//int getsockname(int socket, struct sockaddr *restrict address,
// socklen_t *restrict address_len);
//RETURN VALUE
//Upon successful completion, 0 shall be returned, the address argu‐
//ment shall point to the address of the socket, and the address_len
//argument shall point to the length of the address. Otherwise, -1
//shall be returned and errno set to indicate the error.
//
//shutdown - shut down socket send and receive operations
//#include <sys/socket.h>
//int shutdown(int socket, int how);
//how Specifies the type of shutdown. The values are as follows:
//SHUT_RD Disables further receive operations.
//SHUT_WR Disables further send operations.
//SHUT_RDWR Disables further send and receive operations.
//RETURN VALUE
//Upon successful completion, shutdown() shall return 0; otherwise,
//-1 shall be returned and errno set to indicate the error.
//
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define PORT 8000
#define BUF_SIZE 1024
int main()
{
struct sockaddr_in serv_addr, clie_addr;
int res;
socklen_t clie_addrlen;
int sockfd;
char buf[BUF_SIZE];
char str[INET_ADDRSTRLEN];
//建立socket连接
//int socket(int domain, int type, int protocol);
//以默认协议,在INET域建立数据报套接字
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Error scoket");
exit(-1);
}
printf("套接字 ID = %d", sockfd);
//设置sockaddr_in结构中的相关参数
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&(serv_addr.sin_zero), 8);
int i = 1; //允许重复使用本地地址与套接字进行绑定
//int setsockopt(int socket, int level, int option_name,
// const void *option_value, socklen_t option_len);
if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) == -1)
{
perror("Error setsockopt");
exit(-1);
}
//绑定端口及服务器地址 bind函数
//int bind(int socket, const struct sockaddr *address,
// socklen_t address_len);
if((bind(sockfd, (struct sockaddr *)&serv_addr,\
sizeof(struct sockaddr))) == -1)
{
perror("Error bind");
exit(-1);
}
printf("绑定成功!\n");
while(1)
{
clie_addrlen = sizeof(clie_addr);
memset(buf, 0, sizeof(buf));
//调用recvfrom 接受客户端请求
//ssize_t recvfrom(int sockfd, void *buf, size_t len,
//int flags, struct sockaddr *src_addr, socklen_t *addrlen);
if((res = recvfrom(sockfd, buf, sizeof(buf), 0,\
(struct sockaddr *)&clie_addr, &clie_addrlen)) == -1)
{
perror("Error recvfrom");
exit(-1);
}
if((inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr,\
str, INET_ADDRSTRLEN)) == NULL)
{
perror("Error inet_ntop after recvfrom");
exit(-1);
}
printf("接收到来自(%s)的消息:%s(%d个字节)\n", str, buf, res);
//调用 sendto 函数回复一条消息
//ssize_t sendto(int socket, const void *message,
// size_t length,int flags,
// const struct sockaddr *dest_addr,socklen_t dest_len);
memset(buf, 0, sizeof(buf));
sprintf(buf, "%s信息已收到!", str);
if((res = sendto(sockfd, buf, strlen(buf), 0,\
(struct sockaddr *)&clie_addr, clie_addrlen)) == -1)
{
perror("Error send");
exit(-1);
}
} //end while(1)
close(sockfd);
exit(0);
}
执行结果
客户端可以带参也可以缺省,用默认值。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不听话的兔子君!