当前位置:   article > 正文

Linux C编程 socket—Udp单播_c socket udp 单拨

c socket udp 单拨

Udp简介

概述

  1. UDP 是 User Datagram Protocol 的简称, 中文名是用户数据报协议,是一个简单的面向数据报的运输层协议,在网络中用于处理数据包,是一种无连接的协议。
  2. UDP 不提供可靠性的传输,它只是把应用程序传给 IP 层的数据报发送出去,但是并不能保证它们能到达目的地。
  3. 由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接(与Tcp不同之处),且没有超时重发等机制,故而传输速度很快。

特点

  1. 邮件系统服务模式的抽象(可通过邮件模型来进行对比)
  2. 每个分组都携带完整的目的地址
  3. 发送数据之前不需要建立链接
  4. 不对数据包的顺序进行检查,不能保证分组的先后顺序
  5. 不进行分组出错的恢复和重传
  6. 不保证数据传输的可靠性
    tips:
    在网络质量令人十分不满意的环境下,UDP 协议数据包丢失会比较严重。但是由于 UDP 的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的 ICQ 和 QQ 就是使用的 UDP

Udp单播编程(服务器和客户端基本无差别)

函数介绍

  • socket函数
 #include <sys/types.h>
 #include <sys/socket.h>
 int socket(int domain, int type, int protocol);
  • 1
  • 2
  • 3
  • domain参数:
    AF_UNIX(本机通信)
    AF_INET(TCP/IP – IPv4)
    AF_INET6(TCP/IP –IPv6)

  • 其中 “type”参数指的是套接字类型,常用的类型有:
    SOCK_STREAM(TCP流)
    SOCK_DGRAM(UDP数据报)
    SOCK_RAW(原始套接字)

  • 最后一个 “protocol”:
    一般设置为“0”,也就是当确定套接字使用的协议簇和类型时,这个参数的值就为0,但是有时候创建原始套接字时,并不知道要使用的协议簇和类型,也就是domain参数未知情况下,这时protocol这个参数就起作用了,它可以确定协议的种类。

  • socket是一个函数,那么它也有返回值,当套接字创建成功时,返回套接字,失败返回“-1”,错误代码则写
    入“errno”中。

所以Udp的套接字应该如下创建:

int sock = socket(AF_INET,SOCK_DGRAM,0);
  • 1
  1. bind函数
    将套接字和本机的信息绑定在一起。
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  • 1
  • 2
  • 3
  1. recvfrom函数
    绑定本机信息之后,可以使用recvfrom函数接收信息
    举个例子,bind函数相当于开启本机的邮筒,recvfrom相当于去邮筒中查看有没有信件(信件中会附带对方的地址)。
#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);
  • 1
  • 2
  • 3
  • 4
  • int sockfd 创建的套接字
  • void *buf 发送的内容
  • size_t len 内容的长度
  • int flags 一般就填 0
  • struct sockaddr *src_addr 发送主机的信息
  • socklen_t *addrlen 结构体的长度
  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);

  • 1
  • 2
  • 3
  • 4
  • 5
  • const struct sockaddr *dest_addr 目标主机的信息

Udp服务器示例

说明:
服务器程序:服务器不需要先向客户端发送,所以只需要绑定自己主机信息,和开启端口(相当于放置邮箱),等待客户端发送信息,客户端一旦发送信息,必然携带相应的主机信息,然后我们在服务端将客户端的信息写入相应的结构体中,知道了对方的主机信息,就可以朝对方发送了,发送时,是内核帮我们完成的绑定本机ip和开启端口的任务。
服务器的任务其实就是收,看自己绑定的端口是否有信息(类似,定期查看邮筒里是否有信件)。

//Udp_server.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include <stdlib.h>

static useAge(const char *proc)
{
		printf("Please Enter: %s [ip] [port]\n",proc);
		
}

int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		useAge(argv[0]);
		exit(1);
	}
	
	int socked =socket(AF_INET,SOCK_DGRAM,0);
	if(socked<0)
	{
		perror("socket error");
		return 1;
	}
	
	struct sockaddr_in local;  //服务器需要知道本机的信息
	local.sin_family=AF_INET;
	local.sin_addr.s_addr=inet_addr(argv[1]);   //INADDR_ANY(网卡上的所有IP)
	local.sin_port=htons(atoi(argv[2]));
	
	if(bind(socked,(struct sockaddr_in*)&local,sizeof(local))<0)
	{
		perror("bind error");
		return 2;
	}
	
	struct sockaddr_in sender;
	socklen_t len =sizeof(sender);
	
	char buf[1024];
	while(1)
	{
		memset(buf,'\0',sizeof(buf));
		recvfrom(socked,buf,sizeof(buf),0,(struct sockaddr_in*)&sender,&len);
		printf("#########################\n");
		printf("Get a cilent:%s: %d : %s\n",inet_ntoa(sender.sin_addr),ntohs(sender.sin_port),buf);
		sendto(socked,buf,sizeof(buf),0,(struct sockaddr_in*)&sender,len);
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

运行效果:
在这里插入图片描述

Udp客户端示例

说明:
客户端程序:客户端需要向服务器发送信息,所以需要知道服务器的主机信息(IP地址和端口号)(好比你给别人寄信,需要知道对方的地址是一样的),当客户端想要接收信息的时候,也需要绑定自己的主机信息。

//Udp_cilent.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include <stdlib.h>

static useAge(const char *proc)
{
		printf("Please Enter: %s [ip] [port]\n",proc);
		
}

int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		useAge(argv[0]);
		exit(1);		
	}
	int socked =socket(AF_INET,SOCK_DGRAM,0);
	if(socked<0)
	{
		perror("socket error");
		return 1;
	}
	struct sockaddr_in remote,local;   //客户端需要知道对方的IP 和 端口等 信息
	remote.sin_family=AF_INET;
	remote.sin_addr.s_addr=inet_addr(argv[1]);   
	remote.sin_port=htons(atoi(argv[2]));
	
	local.sin_family=AF_INET;    
	local.sin_addr.s_addr=htonl(INADDR_ANY);   
	local.sin_port=htons(8888);
	
	if(bind(socked,(struct sockaddr_in*)&local,sizeof(local))<0)
	{
		perror("bind error");
		return 2;
	}
	
	struct sockaddr_in sender;
    socklen_t len = sizeof(sender);
	
	char buf[1024];
	while(1)
	{
		memset(buf,'\0',sizeof(buf));
        printf("Please Enter:");
        fflush(stdout);
        ssize_t length = read(0,buf,sizeof(buf)-1 );  //从标准输入读入buf ,回车不读
        if(length > 0){
            buf[length -1] = '\0';
            sendto(socked,buf,sizeof(buf),0,(struct sockaddr*)&remote,sizeof(remote));
            memset(buf,'\0',sizeof(buf));
            recvfrom(socked,buf,sizeof(buf),0,(struct sockaddr*)&sender,&len);
            printf("#########################\n");
			printf("Get a server:%s: %d : %s\n",inet_ntoa(sender.sin_addr),ntohs(sender.sin_port),buf);
        }	
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/187193
推荐阅读
相关标签
  

闽ICP备14008679号