第8章基本UDP套接口编程

第8章基本UDP套接口编程

先介绍UDP的接受和发送函数
ssize_t sendto(int fd,void* buff,size_t nbytes,int flag,sockaddr* addr,socklen_t *len)
ssize_t recvfrom(int fd,void*buff,size_t nbytes,int flag,sockassr* addr,socklen_t *len)

fd 是打开的套接字

buff是发送数据,nbytes是数据的长度

int flag是设置的标志

addr是发送和接受的地址,len是地址的长度

返回值是读写成功的长度

UDP写一个长度为0的数据报是可以的。接受端接受到为0的数据报并不表示发送端发送的是FIN数据报

如果recvfrom的地址和地址长度都设置成NULL表示我们对地址和长度不感兴趣

UDP的回射程序:

贴代码:

服务器端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <string.h>

#define SERV_IP "127.0.0.1"
#define SERV_PORT 9999
#define MAX_LINE 1024

void dump_sock(int fd)
{
	struct sockaddr_in recv_addr;
	char recv_data[MAX_LINE+1] = {0};
	int len = sizeof(recv_addr);
	while(1)
	{
		int size = recvfrom(fd, recv_data, MAX_LINE, 0, (struct sockaddr*)&recv_addr,\
&len);
		sendto(fd, recv_data, MAX_LINE, 0, (struct sockaddr*)&recv_addr, len);
		printf("**********data************\n");
		printf("%s\n",recv_data);
		memset(recv_data, 0, MAX_LINE+1);
	}
}
int main()
{
	int fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd == -1)
	{
		perror("socket execute fail\n");
		return -1;
	}
	struct sockaddr_in addr;
	int len = sizeof(addr);
	addr.sin_family = AF_INET;
	inet_pton(AF_INET, SERV_IP, &addr.sin_addr);
   	addr.sin_port = htons(SERV_PORT);
	bind(fd,(struct sockaddr*)&addr, len);
	dump_sock(fd);
	return 0;
}


客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 9999
#define MAX_LINE 1024
void dump_send(int fd, struct sockaddr_in* addr)
{
    char send_data[MAX_LINE+1] = {0};
    char recv_data[MAX_LINE+1] ={0};
    int len = sizeof(structsockaddr_in);
    while(fgets(send_data, MAX_LINE,stdin) != NULL)
    {
        int size = sendto(fd,send_data,strlen(send_data), 0, (struct sockaddr*)addr,\
len);
        recvfrom(fd, recv_data,MAX_LINE, 0, NULL, NULL);
        write(STDOUT_FILENO,recv_data, strlen(recv_data));
    }
}
int main()
{
    struct sockaddr_in addr;
    int len = sizeof(addr);
    addr.sin_family = AF_INET;
    inet_pton(AF_INET, SERV_IP,&addr.sin_addr);
    addr.sin_port = htons(SERV_PORT);
    int fd = socket(AF_INET,SOCK_DGRAM, 0);
    if(fd == -1)
    {
        perror("socketfailed\n");
        return -1;
    }
    dump_send(fd, &addr);
    exit(0);
 
}


UDP是不建立连接的,只要客户端有数据发送,那个服务器就接受,只要客户端指定了服务器的ip和port就能把数据发送给服务器

服务器的api顺序是1 socket 2 bind 3 recvfrom 4sendto

客户端的调用顺序是1socket 2 sendto 3 recvfrom

客户端的ip和port如果没有绑定的话(bind),在sendto调用的时候,就会检测,如果没有,那么内核就会给该套接字临时生成一个ip和port来进行通讯

 

UDP的connect方法

UDP进行connect内核只是记录对方的ip和port,他们包含在传递给connect的sock_fd中。并且connect立即返回调用进程

已连接和未连接的套接字的区别:

1是已连接的套接字在发送数据的时候,不用再给他传递地址了,因为connect的时候指定了这个传递的ip和port,已连接的客户端,我们用write send来发送数据

2同理,已连接接受的时候,调用read或者recv了

3 已连接的UDP套接口,当出现异步错误的时候会传递给进程,但是未连接的UDP套接口是不接受错误信息的

任何其他的ip或者端口都不能把数据传递到该套接口,如果该主机上的接受到数据,但是这个数据报的目的端口没有进程,那么主机直接发送一个ICMP数据报

如果客户端想和多个服务器发送消息的话,就最好不要connect

对已连接的套接口调用多次connect的话,能够改变发送的服务器地址或port,如果connect的地址中的地址族是AF_UNSPEC的话,就直接断掉连接,并且返回一个FAFNOSUPPORT的错误代码

 

已连接和未连接的性能:

未连接发送2次数据:

连接套接口

发送数据1

断开套接口

连接套接口

发送数据

断开连接

已连接发送2次数据:

连接套接口

发送数据1

发送数据2

 

UDP不能进行流量控制,如果发送端处理的速度比接受端快很多的话,那么发送端就发的数据很多,当把该套接字的缓冲区写满的时候(发送端比接受端快)这个时候,接受端就会丢失信息,也不进行重发,导致数据报丢失




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值