Linux socket udp/ip编程

创建socket:socket()

准备通信地址:struct sockaddr_in

绑定socket和addr :bind()

进行通信:sendto()/recvfrom

关闭socket:close()

客户端:

创建socket:socket()

准备通信地址:服务器的地址

进行通信:sendto()/recv()

关闭socket:close()

需要的头文件 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> ssize_t() //向指定的socket和相应的地址发送消息,成功返回实际发送数据的大小,失败返回-1设errno ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

dest_addr:目标地址(收件人信息)
addrlen: 目标地址的大小

ANote

send(sockfd, buf, len, flags);等价于 sendto(sockfd, buf, len, flags, NULL, 0);

recv()/ send()表示通过sockfd收发数据, 因为tcp下, 收发之前sockfd已经和相应的地址连接了,所以不需要指定收发谁的/给谁, 但是udp因为收发时没有连接, 所以需要指定

recvfrom() //从指定的socket和相应的地址接受消息,并提供来电显示的功能,成功返回实际接收的数据大小,失败返回-1设errno ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

src_addr: 结构体指针, 用于保存数据发送方的通信地址
addrlen: 指针类型, 用于保存发送方的地址大小

Note:

recv(sockfd, buf, len, flags); 等价于 recvfrom(sockfd, buf, len, flags, NULL, 0);

accept() and recvfrom() 后面的参数是用来提供来电显示的

Notation:

一个server对应多个client

server可以不知道client的地址, 但是client得知道server的地址

send data 一定要知道对方地址

receive data不需要知道对方地址

TCP/IP的socket都是SOCK_STREAM的,全程连接,通过socket就能找到对方地址, send data的话,直接丢给socket就行

UDP/IP的socket是SOCK_DGRAM的,不全程连接,不能通过socket找到对方,send data的话,server中需要使用recvfrom()来知道client的地址, 所以肯定要sendto();client本来就知道server的地址, 直接sendto()
综上:

    server   client  
TCP/IP   send();recv()   send();recv()  
UDP/IP   recvfrom();sendto()   recv();sendto()  

recvfrom()的唯一意义就是在udp-server中配合sendto()使用

因为不能通过socket找到对方, 只要是udp发消息, 就得通过sendto()

例子 //udp/ip server 五步走 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> int main(){ //1. 创建socket int sockfd=socket(AF_INET,SOCK_DGRAM,0); if(-1==sockfd) perror("socket"),exit(-1); //2. 准备通信地址 struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port=htons(8888); addr.sin_addr.s_addr=inet_addr("176.43.11.211"); //3. 绑定socket和通信地址 int res=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)); if(-1==res) perror("bind"),exit(-1); printf("bind success\n"); //4. 进行通信 char buf[100]={0}; struct sockaddr_in recv_addr; //为使用recvfrom得到client地址做准备, 最终为sendto()做准备 socklen_t len=sizeof(recv_addr); res=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&len); if(-1==res) perror("recvfrom"),exit(-1); char* ip=inet_ntoa(recv_addr.sin_addr); //将recvfrom获得client地址转换成点分十进制字符串 printf("data received from client :%s is:%d\n",ip,res); res=sendto(sockfd,"I received",sizeof("I received"),0,(struct sockaddr*)&recv_addr,len);//使用recvfrom获得的client地址 if(-1==res) perror("sendto"),exit(-1); //5. 关闭socket res=close(sockfd); if(-1==res) perror("close"),exit(-1); printf("close success\n"); return 0; } //udp/ip client #include<stdio.h> #include<stdlib.h> #include<unistd.h> //close() #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> int main(){ int sockfd=socket(AF_INET,SOCK_DGRAM,0); if(-1==sockfd) perror("socket"),exit(-1); printf("create socket succesfully\n"); struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port=htons(8888); addr.sin_addr.s_addr=inet_addr("176.43.11.211"); //这个是server的地址, 虽然没有connect, which means 不能通过socket找到这个地址, 但是我们还是知道这个地址的, sendto()是可以直接用的 int res=sendto(sockfd,"hello",sizeof("hello"),0,(struct sockaddr*)&addr,sizeof(addr)); if(-1==res) perror("sendto"),exit(-1); printf("data sent size:%d\n",res); char buf[100]={0}; res=recv(sockfd,buf,sizeof(buf),0); if(-1==res) perror("recv"),exit(-1); printf("data received from server:%s\n",buf); res=close(sockfd); if(-1==res) perror("close"),exit(-1); return 0; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d8096f5fba365fcab91663c635dab3c7.html