socket
网络API(应用程序编程接口),实现相同或不同主机上的进程通信
头文件:
#include <sys/types.h>
#include <sys/socket.h>
原型:
int socket(int domain, int type, int protocol);
参数:
int domain:Linux支持的协议族(地址族);
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7);
int type:套接字类型
SOCK_STREAM:字节流式套接字----> TCP
SOCK_DGRAM: 数据报式套接字----> UDP
SOCK_RAW:原始套接字,传输协议需要在第三个参数指定;
int protocol:传输协议。如果不需要填0;
IPPROTO_TCP 和 IPPROTO_UDP;
返回值:
成功,返回套接字的文件描述符;
失败,返回-1,更新errno;
例程:
//UDP
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
perror("socket");
return -1;
}
bind
服务器:(必须)绑定本地的IP和端口号到套接字
客户端:(非必需)绑定本地的IP和端口号到套接字
头文件:
#include <sys/types.h>
#include <sys/socket.h>
原型:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
int sockfd:socket创建的套接字;
struct sockaddr *addr:通用地址结构体,一般不采用该结构体,不同的协议族采用不同的地址结构体(详见socket),调用时强制转换到通用地址结构体;
socklen_t addrlen:地址结构体的大小,sizeof(struct sockaddr_in);
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
saddr.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr)) < 0)
{
ERR_LOG("bind");
return -1;
}
recvfrom
接收发送端的数据,并获取发送端的IP和端口号
头文件:
#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);
参数:
int sockfd:socket创建的套接字;
void *buf:存储接收到的数据;
size_t len:要接收的长度;
int flags:接收方式,0:阻塞方式接收;
struct sockaddr *src_addr:通用地址结构体,存储发送端的IP和端口号。如果不想接收,填NULL;
socklen_t *addrlen:第五个参数地址结构体的大小,注意是指针类型;
返回值:
>0,返回接收到的字节数;
==0; 对方关闭,只能用于TCP;
-1;错误,更新errno;
例程:
//服务端
struct sockaddr_in caddr;
socklen_t caddr_len = sizeof(caddr);
char buf[N] = "";
res = recvfrom(sfd,buf,N,0,(struct sockaddr*)&caddr,&caddr_len);
if(res < 0)
{
ERR_LOG("recvfrom");
return -1;
}
printf("[%s:%d]:",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
puts(buf);
//客户端
if(recvfrom(sfd, buf, N, 0, NULL, NULL) < 0)
{
ERR_LOG("recvfrom");
return -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);
参数:
int sockfd:socket创建的套接字;
void *buf:存储要发送的数据;
size_t len:指定要发送的数据大小;
int flags:发送方式,填0,阻塞方式发送。如果没有数据发送,则阻塞在该函数上;
struct sockaddr *dest_addr:存储着目标的IP和端口,据此来发送;
socklen_t addrlen:地址结构体的大小;
返回值:
成功,返回发送成功的字节数;
失败,返回-1,更新errno;
例程:
//服务器
if(sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&caddr,caddr_len) < 0)
{
ERR_LOG("sendto");
return -1;
}
//客户端
if(sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&saddr,sizeof(saddr))<0)
{
ERR_LOG("sendto");
return -1;
}
UDP模型
UDP服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define ERR_LOG(msg) do{\
perror(msg);\
printf("%d %s %s\n",__LINE__,__func__,__FILE__);\
}while(0)
#define IP "192.168.1.141"
#define PORT 8888
#define N 128
int main(int argc, const char *argv[])
{
//1、创建socket套接字
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
ERR_LOG("socket");
return -1;
}
//2、bind服务器的IP & PORT
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
saddr.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr)) < 0)
{
ERR_LOG("bind");
return -1;
}
struct sockaddr_in caddr;
socklen_t caddr_len = sizeof(caddr);
char buf[N] = "";
int res;
while(1)
{
//3、recvfrom接收数据
bzero(buf,sizeof(buf));
res = recvfrom(sfd,buf,N,0,(struct sockaddr*)&caddr,&caddr_len);
if(res < 0)
{
ERR_LOG("recvfrom");
return -1;
}
printf("[%s:%d]:",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
puts(buf);
//4、sendto发送数据
strcat(buf,"*_*");
if(sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&caddr,caddr_len) < 0)
{
ERR_LOG("sendto");
return -1;
}
}
//5、close文件描述符
close(sfd);
return 0;
}
UDP客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define ERR_LOG(msg) do{\
perror(msg);\
printf("%d %s %s\n",__LINE__,__func__,__FILE__);\
}while(0)
#define IP "192.168.1.141"
#define PORT 8888
#define N 128
int main(int argc, const char *argv[])
{
//1、创建socket套接字
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
ERR_LOG("socket");
return -1;
}
//2、填充服务器ip&port信息
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
saddr.sin_addr.s_addr = inet_addr(IP);
char buf[N] = "";
int res;
while(1)
{
//3、recvfrom接收数据
bzero(buf,sizeof(buf));
res = recvfrom(sfd,buf,N,0,NULL,NULL);
if(res < 0)
{
ERR_LOG("recvfrom");
return -1;
}
printf("[%s:%d]:",inet_ntoa(saddr.sin_addr),ntohs(saddr.sin_port));
puts(buf);
//4、sendto送数据
strcat(buf,"*_*");
if(sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&saddr,sizeof(saddr)) < 0)
{
ERR_LOG("sendto");
return -1;
}
}
//5、close文件描述符
close(sfd);
return 0;
}
本文链接:https://shengto.top/network_programming/udp_model.html
转载时须注明出处及本声明