一、数据报socket编程
服务端:
struct sockaddr_in svaddr,claddr; int sockfd; char buf[256]; sockfd = socket(AF_INET, SOCK_DGRAM,0);//创建socket memset(&svaddr, 0x00, sizeof(struct sockaddr_in));//填写服务端地址 svaddr.sin_family = AF_INET; svaddr.sin_addr.s_addr = htonl(INADDR_ANY); svaddr.sin_port = htons(50000); bind(sockfd,(struct sockaddr*)&svaddr, sizeof(svaddr));//绑定sockfd和服务端地址 int len = sizeof(struct sockaddr_in); recvfrom(sockfd, buf,BUF_SIZE, 0, (struct sockaddr*)&claddr, &len);//注意这里的地址是客户端的地址,可以理解,是从客户端接受的,会返回客户端地址信息在claddr结构中
客户端:
struct sockaddr_in svaddr; char str[] = "helloworld"; char ipstring[256] = "127.0.0.1"; int sockfd = socket(AF_INET, SOCK_DGRAM,0);//创建socket memset(&svaddr ,0, sizeof(struct sockaddr_in));//依然填写服务端地址 svaddr.sin_family = AF_INET; svaddr.sin_port = htons(50000); inet_pton(AF_INET, ipstring,&svaddr.sin_addr); int len = sizeof(struct sockaddr_in); sendto(sockfd, str,sizeof(str),0,(struct sockaddr*)&svaddr,len);//接受,从服务端,注意最后一个参数是len
inet_pton函数中,ipstring参数,必须是数组形式即char ipstring[],如果定义char *ipstring并传入ipstring会出现段错误。
二、使用msg来传递消息
服务端:
struct sockaddr_in svaddr; int sockfd; struct sockaddr_in *claddr; char buf[256]; sockfd = socket(AF_INET, SOCK_DGRAM,0); memset(&svaddr, 0x00, sizeof(struct sockaddr_in)); svaddr.sin_family = AF_INET; svaddr.sin_addr.s_addr = htonl(INADDR_ANY); svaddr.sin_port = htons(50000); bind(sockfd,(struct sockaddr*)&svaddr, sizeof(svaddr));//到这里为止,都是一般的socket创建方法 struct msghdr msg; claddr = malloc(sizeof(struct sockaddr_in));//开始填写msghdr结构 msg.msg_name = claddr;//将客户端地址填入 msg.msg_namelen = sizeof(struct sockaddr_in); struct iovec iov; iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; size_t len = recvmsg(sockfd, &msg,0);//msg中会返回客户端的地址,与recvfrom相似。 claddr = msg.msg_name; char *temp = msg.msg_iov[0].iov_base; close(sockfd);
客户端:
nt main() { struct sockaddr_in svaddr; struct msghdr msg; struct iovec iov; char str[] = "helloworld"; char ipstring[256] = "127.0.0.1"; memset(&msg,0,sizeof(struct msghdr)); iov.iov_base = str;//将希望发送的数据填好 iov.iov_len = sizeof(str); int sockfd = socket(AF_INET, SOCK_DGRAM,0);//同样的创建好服务端的socket地址 memset(&svaddr ,0, sizeof(struct sockaddr_in)); svaddr.sin_family = AF_INET; svaddr.sin_port = htons(50000); inet_pton(AF_INET, ipstring,&svaddr.sin_addr); msg.msg_name = &svaddr;//将服务端地址填入 msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_iov = &iov; msg.msg_iovlen = 1; ssize_t size = sendmsg(sockfd, &msg, 0); close(sockfd); }
对比两者,服务端和客户端都要创建并填写好svaddr。sendto sendmsg,recvfrom recvmsg中地址参数是对方地址;并且recvfrom recvmsg都可以返回客户端地址信息。