UDP

  1. UDP的通讯方式

服务器来说:

 

(1)新建socket

        #include <sys/types.h>          /* See NOTES */

        #include <sys/socket.h>

 

        int socket(int domain, int type, int protocol);

第一个参数:指定域,协议族

        AF_UNIX, AF_LOCAL   Local communication              unix(7)    建立UNIX的协议

        AF_INET             IPv4 Internet protocols          ip(7) 这个代表使用IPV4的协议族  ----> 32bit

        AF_INET6            IPv6 Internet protocols          ipv6(7) 这个代表使用IPV6的协议族  ----> 128bit

 

第二个参数:指定我们创建的套接字的类型

SOCK_STREAM    提供一种有序的、可靠、双向的,基于连接的字节流类型的一种套接字。        ----> TCP

        SOCK_DGRAM     提供一种数据报的通讯方式,这种方式是无连接的,不可靠的,有固定最大数据通讯长度的这一种套接字  ----> UDP

 

第三个参数:指定该套接字用这个协议族里面的哪个子协议。一般都用0。

 

 

返回值:如果成功这个新建的套接字的fd,就会返回。如果出错就会返回-1。

 

(2)绑定bind

        #include <sys/types.h>          /* See NOTES */

        #include <sys/socket.h>

 

        int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

第一个参数:就是前面返回的文件描述符。

第二个参数:指定我们通讯的地址,这个是一个通用的结构体,它的地址,由指定的协议族去决定的。

第三个参数:指定的是第二个参数地址的大小。

返回值:

如果成功返回0;

如果失败返回-1;

 

通用的结构体:

            struct sockaddr {

                sa_family_t sa_family; //指定所用的协议族。

                char        sa_data[14]; //这里是具体的地址填充的空间。

            }

在头文件里面:#include <netinet/in.h>

/* Internet address.  */

typedef uint32_t in_addr_t; //表示其IP地址

struct in_addr  

{

in_addr_t s_addr; //这个IP地址,实际上是一个32位无符号的数据

};

/* Type to represent a port.  */

 

 

IP地址的分类:A类、B类、C类、D类、E类(地址包含有网络号+主机号)

将点分式的IP地址,变成我们对应的32位的数据:

 

sockaddr_in.sin_addr = inet_addr("192.168.5.2");

inet_aton("192.168.5.2", &sockaddr_in.sin_addr);

 

 

 

描述我们网络socket地址     /* Structure describing an Internet socket address.  */

 

typedef uint16_t in_port_t; //16位的端口号

struct sockaddr_in

  {

    __SOCKADDR_COMMON (sin_);  //协议族

    in_port_t sin_port;        //端口号 2字节

    struct in_addr sin_addr;   //IP地址 4字节

    unsigned char sin_zero[8]; //填充8个字节,使其和其他的协议族的地址结构体大小一致。

  };

 

端口号:

小端的保存方式,低地址保存低位的数据。

大端的保存方式,低地址保存高位的数据。

 

#include <arpa/inet.h>

h-->host(主机)

n-->network(网络)

l-->代表是32位

s-->代表是16位

htonl();

htons();

ntohl();

ntohs();

 

 

(3)等待客户端发信息过来 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);

第一个参数:是前面socket函数返回的fd。代表我们要和对应的客户端进行通讯。

第二个参数:是我们要发送或者接收的buffer对应的地址。

第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。

第四个参数:一般都是0;

第五个参数:用来保存客户端的地址信息。

第六个参数:就是前面这个地址的长度。

返回值:成功的话,返回值的大小代表实际读取的字节数。这个返回值,和count不一定相等。

如果出错的话,返回-1;

ret = recvfrom(serverfd,buf,128,0,(struct sockaddr *)&clientaddr,&sin_size);//注意两个函数的最后一个参数

 

(4)可以获取到客户端的地址信息之后,大家就可以互相通讯了。

ret = sendto(serverfd,buf,strlen(buf),0, (struct sockaddr *)&clientaddr,sin_size );

 

 

(5)通讯结束之后,关闭连接。

服务器端:

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

 

int main()

{

int serverfd;

int clientfd;

int ret;

// 1 、创建一个socket 指定socket的类型为数据报的类型,UDP

serverfd = socket(AF_INET,SOCK_DGRAM,0);

if(serverfd < 0)

{

perror("socket create fail");

return -1;

}

//声明两个地址结构体,一个地址结构体用来保存服务器绑定的地址

//第二个结构体用来保存客户端发过来的地址。

struct sockaddr_in serveraddr;

struct sockaddr_in clientaddr;//用来在通信时保存客户端的地址;

memset(&serveraddr,0,sizeof(serveraddr));

memset(&clientaddr,0,sizeof(clientaddr));

//初始化服务器要绑定的地址结构体

serveraddr.sin_family = AF_INET;//表示所用的协议族

serveraddr.sin_addr.s_addr = INADDR_ANY; //表示接受任意ip的请求

serveraddr.sin_port = htons(8000); //表示对应的端口号,客户端就可以通过这个端口进行通讯

// 2、绑定我们的地址和端口号,先初始化这个地址

ret = bind(serverfd,(struct sockaddr * )&serveraddr,sizeof(struct sockaddr_in));

if(ret < 0)

{

perror("bind fail");

close(serverfd);

return -1;

}

 

int sin_size = sizeof(struct sockaddr_in);//不转的话编译会通不过;

 

char buf[128];

memset(buf,0,128);

//接收客户端发送过来的数据,并且将客户端的地址保存到

//clientaddr内,以后要跟客户端通讯就可以使用这个地址进行发送数据。

ret = recvfrom(serverfd,buf,128,0,(struct sockaddr *)&clientaddr,&sin_size);

printf("Recv msg from client :%s\n",buf);

 

bzero(buf,128);

fgets(buf,128,stdin);

//发送数据给客户端,对应的地址就是上面接收函数保存下来的地址

ret = sendto(serverfd,buf,strlen(buf),0, (struct sockaddr *)&clientaddr,sin_size );

 

//关闭对应的fd。

close(serverfd);

 

 

}

 

自己代码:

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include<stdlib.h>

 

int main()

{

int serverfd;

int clientfd;

 

int ret;

// 1 、创建一个socket

serverfd = socket(AF_INET,SOCK_DGRAM ,0);//数据报;

if(serverfd < 0)

{

perror("socket create fail");

return -1;

}

int reuse=0;

ret=setsockopt(serverfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));

 

struct sockaddr_in serveraddr;//声明一个结构体变量;

struct sockaddr_in clientaddr;

memset(&serveraddr,0,sizeof(serveraddr));//对结构体清零;

memset(&clientaddr,0,sizeof(clientaddr));

 

serveraddr.sin_family = AF_INET;//协议族为ipv4

serveraddr.sin_addr.s_addr = INADDR_ANY; //表示接受任意ip的请求

serveraddr.sin_port = htons(8002); //表示对应的端口号,客户端就可以通过这个端口进行通讯

// 2、绑定我们的地址和端口号,先初始化这个地址

ret = bind(serverfd,(struct sockaddr * )&serveraddr,sizeof(struct sockaddr));

 

if(ret < 0)

{

perror("bind fail");

close(serverfd);

return -1;

}

char buf[128];

memset(buf,0,128);

int size=sizeof(struct sockaddr);

while(1)

{

recvfrom(serverfd, buf,128, 0,(struct sockaddr *)&clientaddr,&size);

printf("recv msg from client:%s\n",buf);

memset(buf,0,128);

printf("please input\n");

fgets(buf,128,stdin);

if( strcmp(buf,"quit") == 0)

break;

sendto(serverfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,size);

}

close(serverfd);

 

 

}

 

 

 

 

    客户端来说:

(1)新建socket

 

(2)初始化好地址结构体。

 

(3)直接发送: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);

第一个参数:是前面socket函数返回的fd。代表我们要和对应的客户端进行通讯。

第二个参数:是我们要发送或者接收的buffer对应的地址。

第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。

第四个参数:一般都是0;

第五个参数:这个是我们要将数据发送到哪里?这个就是接收方的地址。这个参数一定要指定。

第六个参数:就是前面这个地址的长度。

返回值:成功的话,返回值的大小代表实际发送的字节数。这个返回值,和count不一定相等。

如果出错的话,返回-1;

 

ret = sendto(clientfd,buf,strlen(buf),0,(struct sockaddr *)&serveraddr,size);

 

 

(4)等待服务器回信:recvfrom

ret = recvfrom(clientfd,buf,128,0,(struct sockaddr *)&serveraddr,&size);

 

  1. 通讯结束之后,关闭连接。

 

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

 

int main()

{

int clientfd;

int ret;

// 1、新建一个socket,这个socket的类型是UDP的方式。

clientfd = socket(AF_INET,SOCK_DGRAM,0);

if(clientfd < 0)

{

perror("create socket fail");

return -1;

}

//声明我们要和谁通讯的地址,并且初始化好它//udp是不连接的方式;

struct sockaddr_in serveraddr;

memset(&serveraddr,0,sizeof(serveraddr));

 

//设置好对应的服务器的地址和端口号

serveraddr.sin_family = AF_INET;

serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");

serveraddr.sin_port = htons(8000);

 

char buf[128];

//从键盘输入一段信息,然后发送给服务器。

memset(buf,0,128);

fgets(buf,128,stdin);

int size = sizeof(struct sockaddr);

ret = sendto(clientfd,buf,strlen(buf),0,(struct sockaddr *)&serveraddr,size);

memset(buf,0,128);

//再从服务器接收其发过来的数据。

ret = recvfrom(clientfd,buf,128,0,(struct sockaddr *)&serveraddr,&size);

printf("Recv from server: %s\n",buf);

// 4、关闭连接。

close(clientfd);

 

}

 

自己代码:

 

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include<stdlib.h>

 

int main()

{

 

int clientfd;

 

int ret;

// 1 、创建一个socket

clientfd = socket(AF_INET,SOCK_DGRAM ,0);//数据报;

if(clientfd < 0)

{

perror("socket create fail");

return -1;

}

int reuse=0;

//ret=setsockopt(serverfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));

 

struct sockaddr_in serveraddr;//声明一个结构体变量;

struct sockaddr_in clientaddr;

memset(&serveraddr,0,sizeof(serveraddr));//对结构体清零;

memset(&clientaddr,0,sizeof(clientaddr));

 

serveraddr.sin_family = AF_INET;//协议族为ipv4

serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");

serveraddr.sin_port = htons(8002); //表示对应的端口号,客户端就可以通过这个端口进行通讯

// 2、绑定我们的地址和端口号,先初始化这个地址

 

 

 

char buf[128];

memset(buf,0,128);

while(1)

{

printf("please input:\n");

fgets(buf,128,stdin);

if( strcmp(buf,"quit") == 0)

break;

 

int size=sizeof(struct sockaddr);

sendto(clientfd, buf,strlen(buf),0,(struct sockaddr *)&serveraddr, size);

memset(buf,0,128);

recvfrom(clientfd,buf,128,0,(struct sockaddr *)&serveraddr, &size);

 

printf("receive from sever2 %s\n",buf);

}

close(clientfd);

 

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值