您的位置:首页 > 编程语言

第8章基本UDP套接口编程

2011-11-06 15:41 281 查看

第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不能进行流量控制,如果发送端处理的速度比接受端快很多的话,那么发送端就发的数据很多,当把该套接字的缓冲区写满的时候(发送端比接受端快)这个时候,接受端就会丢失信息,也不进行重发,导致数据报丢失
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息