网络编程(2)TCP与UDP协议

1.概念

1.1TCP

概念:

TCP(Transmission Control Protocol)协议指的是传输控制协议,是一个面向连接的传输协议,他是一个能提供高可靠性的通信协议,所谓高可靠性指的是数据无丢失、数据无误、数据无失序、数据无重到达。(打电话)

适用场景:

  • 适用于对传输质量要求较高,以及传输大量数据的通信。
  • 在需要传输可靠数据的场合通常会选择使用TCP通信协议。
  • 比如QQ/微信/支付宝等通信软件的账户登录和支付相关功能是通常采用可靠的TCP通信协议来实现。

1.2UDP

概念:

UDP(User Datagram Protocol)指的是用户数据报协议,是一种不可靠无连接的协议,在数据发送前,不需要提前建立连接,所以可以更高效地传输数据。(发邮件)

适用场景:

  • 发送小尺寸地数据(例如对DNS服务器进行地址查询或路游器更新路由表)
  • 在收到数据,给出应答比较困难地网络中适用UDP(比如无线网络)
  • 适用于广播/组播式通信。
  • QQ/微信等即时通信软件地点对点文件通讯以及音视频通话时。
  • 流媒体、VoIOP、IPTV等网络多媒体服务中(直播间)

2.API接口:

2.1TCP 实现通信

2.1.1服务器端:

1.创建TCP套接字
//int socket(int domain, int type, int protocol);

// 创建一个TCP套接字并返回描述符
int sock_fd socket(AF_INET, SOCK_STREAM , 0 );
if (-1 == sock_fd)
{
    perror("socket error");
    return -1;
}
2.绑定IP地址到和端口号
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

//配置端口号和IP信息
    struct sockaddr_in my_addr; 
    int addr_len = sizeof(my_addr); // 计算地址结构体大小
    my_addr.sin_family = AF_INET ; // 选择为IPV4地址
    my_addr.sin_port = htons(65000); // 配置端口号, 注意转为网络字节序
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置IP地址并转为网络字节序 

    // 绑定地址和端口等信息与套接字
    int ret_val = bind(sock_fd , (struct sockaddr *)&my_addr, addr_len);
    if (-1 == ret_val)
    {
        perror("绑定失败");
        return -1; 
    }
3.把套接字设置为监听状态
// 把配置好的套接字设置为监听状态
    ret_val = listen( sock_fd , 5);
    if (-1 == ret_val)
    {
        perror("设置监听失败");
        return -1 ;
    }
4.等待客户端连接
// 等待客户端连接
    struct sockaddr_in other_addr;
    int connect_fd accept(sock_fd , (struct sockaddr *)&other_addr, &addr_len);
    if (connect_fd == -1)
    {
        perror("连接失败");
        return -1 ;
    }
5.接收客户端来消息
// 等待客户端发话 
    char * msg = calloc(1, 1024);
    ret_val = recv(sock_fd , msg , 1024 , 0);
    if (-1 == ret_val)
    {
        perror("接收失败");
        return -1 ;
    }
    else
    {
        printf("鱼头怪老大说:%s\n" , msg);
    } 
6.挂断电话
close(sock_fd);

2.2.2客户端:

1.创建套接字
// 创建一个TCP套接字并返回描述符
    int sock_fd = socket(AF_INET, SOCK_STREAM , 0 );
    if (-1 == sock_fd)
    {
        perror("socket error");
        return -1;
    }
2.连接服务器 
//配置端口号和IP信息
    struct sockaddr_in serve_addr; 
    int addr_len = sizeof(serve_addr); // 计算地址结构体大小
    serve_addr.sin_family = AF_INET ; // 选择为IPV4地址
    serve_addr.sin_port = htons(65000); // 配置端口号, 注意转为网络字节序
    serve_addr.sin_addr.s_addr = inet_addr("172.17.194.54"); // 设置IP地址并转为网络字节序 

    //发起连接请求
    int ret_val = connect(sock_fd , (struct sockaddr *)&serve_addr, addr_len );
    if (ret_val == -1 )
    {
        perror("发起连接失败");
        return -1 ;
    }
    printf("连接成功!!!\n" );
3.发送消息
// 获取输入并发送
    char * msg = calloc(1, 1024);
    fgets(msg , 1024 , stdin );

    ret_val = send(sock_fd , msg , strlen(msg), 0 );
    if (-1 == ret_val)
    {
        perror("发送失败");
        return -1 ;
    }
    else
    {
        printf("发送成功:%s\n" , msg);
    }
4.挂断电话
close(sock_fd);

2.2UDP 实现通信

2.2.1服务端

1. 创建信箱
//创建信箱
    int sock_fd = socket(AF_INET, SOCK_DGRAM , 0);
    if (-1 == sock_fd)
    {
        perror("socket failed");
        return -1 ;
    }
2. 设置信箱地址和端口号
//设置信箱地址
    /*  struct sockaddr_in
        {
            u_short sin_family; // 地址族
            u_short sin_port; // 端口
            struct in_addr sin_addr; // IPV4 地址
            char sin_zero[8];
        };
    */

    struct sockaddr_in addr;
    int addrlen = sizeof(struct sockaddr_in);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(65000);
    addr.sin_addr.s_addr = inet_addr("172.17.194.54");

    //帮定地址
    int ret = bind(sock_fd, (struct sockaddr *)&addr, addrlen);
    if ( -1 == ret )
    {
        printf("bind failed !!\n");
    }else{
        printf("bind succees !!\n");
    }
3. 等待客户端来信
//等待来信
    struct sockaddr_in addr_from;
    char buf[100];
    while(1)
    {   
        bzero(buf,100);
        ret = recvfrom( sock_fd, buf, 100 , 0 , 
                            (struct sockaddr *)&addr_from, &addrlen);
        printf("msg: %s port: %d\naddr: %s\n",
                buf,ntohs(addr_from.sin_port),
                inet_ntoa(addr_from.sin_addr));
    }
4. 关闭信箱
close(sock_fd);

2.2.2客户端:

1. 创建信箱
//创建信箱
    int sock_fd = socket(AF_INET, SOCK_DGRAM , 0);
    if (-1 == sock_fd)
    {
        perror("socket failed");
        return -1 ;
    }
2. 先设置好信件发送的地址
//设置信箱地址
    /*  struct sockaddr_in
        {
            u_short sin_family; // 地址族
            u_short sin_port; // 端口
            struct in_addr sin_addr; // IPV4 地址
            char sin_zero[8];
        };
    */

    struct sockaddr_in addr;
    int addrlen = sizeof(struct sockaddr_in);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(65000);
    addr.sin_addr.s_addr = inet_addr("172.17.194.54");
3. 写信并发送

    //写信
    int ret ;
    char buf[100];
    while(1)
    {   
        bzero(buf,100);
        fgets(buf,100 , stdin);
        ret = sendto( sock_fd, buf, strlen(buf) , 0 , (struct sockaddr *)&addr, addrlen);
        if ( -1 == ret )
        {
            perror("sendto failed ");
        }else{
            printf("sendto succeed !! \n");
        }
    }
4. 关闭信箱
close(sock_fd);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值