基于UDP编程函数接口——socket、sendto、bind、recvfrom(基础快速解读和示例)

一、socket

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

功能:

创建用来通信的终端节点并返回文件描述符

参数:

domain:支持的协议族 AF_INET  (IPv4协议族)

type:套接字的类型

SOCK_STREAM 流式套接字(用于TCP)

SOCK_DGRAM 数据报套接字(用于UDP)

SOCK_RAM 原始套接字

protocol: 默认为0

返回值:

成功返回建立用来通信的新文件描述符,失败返回-1

例子:

二、sendto

sendto:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

功能:

向另外一个套接字发送信息

参数:

sockfd:套接字文件描述符

buf:发送数据空间首地址

len:发送数据长度

flags:默认为0

dest_addr:目的IP地址存放空间首地址

addrlen:目的地址的长度

返回值:

成功返回实际发送的字节数,失败返回-1

struct sockaddr_in {
                               sa_family_t    sin_family; /* address family: AF_INET */
                               in_port_t      sin_port;   /* port in network byte order */
                               struct in_addr sin_addr;   /* internet address */
                                };

struct in_addr {
                       uint32_t       s_addr;     /* address in network byte order */
                        };

 inet_addr:
 in_addr_t inet_addr(const char *cp);
将字符串IP地址类型转换为内存中二进制的IP地址类型

inet_ntoa:
char *inet_ntoa(struct in_addr in);
将内存中二进制IP地址类型转换为字符串IP地址类型

htons
uint16_t htons(uint16_t hostshort);
将本地字节序转换为网络字节序(短整形)
          
ntohs
uint16_t ntohs(uint16_t netshort);
将网络字节序转换为本地字节序

例子:(作为客户端cli.c)

#include "head.h"//头文件 

int main(int argc, char const *argv[])
{
    struct sockaddr_in ser;
    char buff[1024] = 0;
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
    perror("fail socket");
    return -1;
    }
    
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);//设置端口号
    ser.sin_addr.s_addr = inet_addr("198.162.1.192");//绑定自己的IP号

    fgets(buff,sizeof(buff),stdin);//从终端输入后sendto发送

   //ssize_t 类型接收send to,判断是否有字节
    ssize_t ret = sendto(sockfd,buff,strlen(buff),0,(struct sockaddr *)&ser,sizeof(ser));
    if(-1 == ret )
    {
        perror("fail sendto");
        return -1;
    }


    return 0;
}

三、bind

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

功能:

将套接字与IP地址和端口绑定

参数:

sockfd:将套接字与IP地址和端口绑定

addr:绑定IP地址空间首地址

addrlen:IP地址的长度

返回值:

成功返回0,失败返回-1

例子:

    int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));//绑定服务端的地址和IP长度
    if (-1 == ret)
    {
        perror("fail bind");
        return -1;
    }

四、resvfrom

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

功能:

接收信息

参数:

sockfd:套接字文件描述符

buf:接收到数据存放空间的首地址

len:最多默认存储的字节数

flags:默认为0

src_addr:存放对方的IP地址长度

addrlen:接收IP地址长度

返回值:

成功返回实际接收字节数,失败返回-1

例子:

(作为客户端cli.c)
#include "head.h"

int main(int argc, char const *argv[])
{
    struct sockaddr_in ser;
    char buff[1024] = {0};
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
    perror("fail socket");
    return -1;
    }
    
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("198.162.1.192");

    while(1)  //一直在检测服务端是否有数据发送
    {
    fgets(buff,sizeof(buff),stdin);
    ssize_t ret = sendto(sockfd,buff,strlen(buff),0,(struct sockaddr *)&ser,sizeof(ser));
    if(-1 == ret )
    {
        perror("fail sendto");
        return -1;
    }
    char p[1024] = {0};
    ssize_t cnt = recvfrom(sockfd,p,sizeof(p),0,NULL,NULL);//对地址不需要存入写NULL
    if(-1 == cnt)
    {
        perror("fail recvfrom");
        return -1;
    }
    printf("ser------->cli:%s\n", buff);

    }

        close(sockfd);
    return 0;
}
(作为服务端ser.c)
#include "head.h"


int main(int argc, const char *argv[])
{
    //socket
    //bind
    //recvfrom
    //close
    
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sockfd)
    {
        perror("fail socket");
        return -1;
    }

    struct sockaddr_in ser, cli;
    socklen_t clilen = sizeof(cli);

    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.1.192");
    int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));
    if (-1 == ret)
    {
        perror("fail bind");
        return -1;
    }
    
    while (1)
    {
        char buff[1024] = {0};
        ssize_t size = recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&cli, &clilen);
        printf("[%s : %d][%ld]: %s\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port) ,size, buff);
        fgets(buff, sizeof(buff), stdin);
        sendto(sockfd, buff, strlen(buff), 0, (struct sockaddr *)&cli, clilen);
    }

    close(sockfd);


    return 0;
}

头文件head.h

#ifndef __HEAD_H__ //防止头文件被重复定义
#define __HEAD_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <poll.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/epoll.h>

#endif

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值