socket UDP的使用

首先明白,对于UDP而言,没有所谓的服务器端和客户端之分,言下之意,就是。。。。疑问疑问疑问

这要写一个程序,就可以代表客户端又可以代表服务器

真这么牛。。。。。。还是看看再说吧!!!!


头文件

#include <sys/types.h>
#include <sys/socket.h>

函数原型

int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

函数说明

sendto(): 是把UDP数据报发给指定地址;

recvfrom(): 是从指定地址接收UDP数据报。

参数说明

s: socket描述符。
buf: UDP数据报缓存地址。
len: UDP数据报长度。
flags: 该参数一般为0。
to: sendto()函数参数,struct sockaddr_in类型,指明UDP数据发往哪里报。
tolen: 对方地址长度,一般为:sizeof(struct sockaddr_in)。
fromlen: struct sockaddr_in类型,指明从哪里接收UDP数据报。

函数返回值

对于sendto()函数,成功则返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。
对于recvfrom()函数,成功则返回接收到的字符数,失败则返回-1,错误原因存于errno中。

struct sockaddr_in结构体

该结构体的定义如下:

/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__	16		/* sizeof(struct sockaddr)	*/
struct sockaddr_in {
    sa_family_t	sin_family;	/* Address family		*/
    __be16		sin_port;	/* Port number			*/
    struct in_addr	sin_addr;	/* Internet address		*/

    /* Pad to size of `struct sockaddr'. */
    unsigned char	__pad[__SOCK_SIZE__ - sizeof(short int) -
        sizeof(unsigned short int) - sizeof(struct in_addr)];
};

其中,

sin_family: 指明地址族,一般使用AF_INET。

sin_port: 指明UDP端口。

sin_addr: 指明IP地址。

INADDR_ANY

INADDR_ANY是个特殊IP地址 ,表示任务的IP地址,作为服务器端的时候经常要用到。作为接收端,当你调用bind()函数绑定IP时使用INADDR_ANY,表明接收来自任意IP、任意网卡的发给指定端口的数据。作为发送端,当用调用bind()函数绑定IP时使用INADDR_ANY,表明使用网卡号最低的网卡进行发送数据,也就是UDP数据广播。关于UDP数据报UDP都是以数据报的形式进行发送和接收的,而TCP是以数据流的形式进行发送和接收的。数据报和数据流,这两者要区分开来。

上面这段话就是说,当你使用多网卡时,每个网卡都有不同的ip,如果你的绑定操作就要针对每个网卡都进行,否则数据就可能得不到处理。现在,INADDR_ANY出现了(其实它就等于0),它允许你就所有网卡看成一个使用,这个网卡的ip就是INADDR_ANY


哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭哭

好吧,我承认我有罪,上面纯属意外,如有雷同,属于我抄袭你

被废话了,进入正题:


具体使用

发送数据:
1.创建socket
int cfd = socket(AF_INET,SOCK_DGRAM,0);
2.发送数据
struct sockaddr_in si_recver;   //接收方的地址	
int addrlen = sizeof(si_recver);
bzero(&si_recver,addrlen);
si_recver.sin_family = AF_INET;
si_recver.sin_port = htons(7000);
si_recver.sin_addr.s_addr = INADDR_ANY;
sendto(cfd,buffer,buffer_size,0,(struct sockaddr *)&si_recver,addrlen);
哈哈,你肯定想说,怎么不绑定一下,呵呵,原来如果你没有绑定,sendto函数内部会替你绑定

接受数据:
1.创建socket
int cfd = socket(AF_INET,SOCK_DGRAM,0);
2.绑定端口和ip地址
struct sockaddr_in si;
int addrlen = sizeof(si);
bzero(&si,addrlen);si.sin_family = AF_INET;
si.sin_port = htons(7500);
si.sin_addr.s_addr = INADDR_ANY;
bind(cfd, (struct sockaddr *)&si, sizeof(si));

 3.接受数据 
 
recvfrom(cfd, buffer, buffer_size, 0, (struct sockaddr*)&si_recver, &addrlen);
好了,到此,全部工作已经完成 微笑 微笑 微笑 微笑 微笑 微笑不对,貌似发送数据缺少绑定,呵呵,管它了,先看看程序能不能正常运行,


#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <poll.h>

#define MAX_RECEIVE_BUFFER 128

int main(int argc,char *argv[]) 
{
	if (argc != 3)
		return -1;
	//1.创建通讯套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if (cfd < 0)
	{
		perror("socket");
		return 0;
	}
	//寻址,这里寻找的地址是用来绑定自己
	struct sockaddr_in si;
	int ret;

	si.sin_family = AF_INET;
	si.sin_port = htons(atoi(argv[1]));
	si.sin_addr.s_addr = INADDR_ANY;

	//2.绑定
	ret = bind(cfd, (struct sockaddr *)&si, sizeof(si));
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}

	// 寻址,这里寻的址是要发送给对方的地址
	//int n = 1;    //这个值用来控制下面设置属性的开关,0表示关,非0启用
	//setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));

	struct sockaddr_in si_recver;   //接收方的地址	
	int addrlen = sizeof(si_recver);
	bzero(&si_recver,addrlen);
	si_recver.sin_family = AF_INET;
	si_recver.sin_port = htons(atoi(argv[2]));
	si_recver.sin_addr.s_addr = INADDR_ANY;
	// 收/发
	int len;
	char buf[MAX_RECEIVE_BUFFER];
	struct pollfd arr[2];
	
	arr[0].fd = 0;//输入设备
	arr[0].events = POLLIN;
	
	arr[1].fd = cfd;//socket
	arr[1].events = POLLIN;
	while(1)
	{	
		poll(arr,2,-1);	
		if (arr[0].revents == POLLIN)
		{
			bzero(buf,MAX_RECEIVE_BUFFER);
			read(0,buf,MAX_RECEIVE_BUFFER);
			sendto(cfd, buf, MAX_RECEIVE_BUFFER-1, 0, (struct sockaddr *)&si_recver, addrlen);
		}
		if (arr[1].revents == POLLIN)
		{
			recvfrom(cfd, buf, MAX_RECEIVE_BUFFER, 0, (struct sockaddr*)&si_recver, &addrlen);
			printf("[%s:%d]:%s\n",(char *)inet_ntoa(si_recver.sin_addr),si_recver.sin_port,buf);
		}
	}

	// 4.关闭套接字
	close(cfd);
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值