Tcp 是 面向连接的 可靠的 流式服务
所以Tcp 需要进行三次握手建立连接后,才可以传输用户数据,可靠性是通过应答确认、超时重传机制等保证,还有滑动窗口来进行流量控制。
Udp 是 无连接 不可靠 数据报服务
所以UDP不需要进行三次握手来建立连接,直接发送数据,不保证可靠交付,不管对方收到还是没有收到。
函数原型:
#include
#include
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t *addrlen);
参数:
sockfd :标识一个已连接套接口的描述字
buf :接收数据缓冲区/发送数据缓冲区
len :缓冲区长度
flags :调用操作方式,flags参数以及返回值的含义与send/recv系统调用的flags参数及返回值相同
src_addr指针 :指向装有源地址的缓冲区(若是面向连接的socket编程,则可以省略这个参数,因为已经建立了连接,所以我们已经知道接收谁的数据,知道它的地址)
dest_addr指针 :指向装有目标地址的缓冲区(若是面向连接的socket编程,则可以省略这个参数,因为已经建立了连接,所以我们已经知道要发送给谁,并且知道他的地址)
addrlen指针 :指向地址缓冲区长度值
实现客户端服务器交互
server.c
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
assert(sockfd != -1 );
//指明地址信息
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
//普通数字可以用htons()函数转换成网络数据格式的数字)
saddr.sin_port = htons(6000);
//将点分十进制的IP地址转化为二进制
saddr.sin_addr.s_addr = inet_addr("192.168.31.225");
//绑定地址信息
int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res != -1);
// UDP不用listen监听
while(1)
{
char buff[128]={0};
int len = sizeof(caddr);
// UDP使用recvform接收数据
// UDP不用accept
int n = recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
assert(n!=-1);
// 输出运行结果
printf("ip=%s,port=%d,buff=%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),buff);
// UDP使用sendto发送数据
sendto(sockfd,"OK",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
close(sockfd);
exit(0);
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
assert(sockfd != -1 );
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("192.168.31.225");
while(1)
{
char buff[128] = {0};
printf("input:\n");
fgets(buff,128,stdin);
if(strncmp(buff,"end",3) ==0 )
{
break;
}
// UDP使用sendto发送数据
sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,128);
int len=sizeof(saddr);
// UDP使用recvform接收数据
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
printf("buff=%s\n",buff);
}
close(sockfd);
exit(0);
}