`
memorymyann
  • 浏览: 271896 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

13.UDP编程

阅读更多

虽然UDP不保证传输的可靠性,但UDP无链接性相对于TCP仍然有其它方面的优势。比如之前的聊天程序,基于TCP实现的聊天程序在群聊方面就很麻烦,因为链接总是双方的通信,很难加入第3方(或许应该说更本就不能加入)。其次UDP没有建立链接过程速度相对来说更快一点(至少它没有三路握手,发送数据也不需要对方确认收到)。

 

UDP编程过程:

服务器端:

1.创建socket

2.绑定端口

3.调用recvfrom获取数据

4.处理请求

5.调用sendto发送数据

 

客户端:

1.创建socket

2.sendto发送数据

3.recvfrom接受数据

4.close

 

没有建立链接的过程,只管接受发送数据(数据丢失,UDP不提供重发,也不会报错,当然不会报错也不是绝对的。比如发送包太大超过了UDP承载限度,则会返回错误。但可惜就是这点报错,不同的地方也不一定都是支持的)。所以相对来说UDP发送小批量数据更为有效,也更为方便。

 

下面介绍下几个之前UDP重要的函数。

 

int socket(AF_INET, SOCK_DGRAM,0)这个之前曾经说过,前2个参数不同的组合则代表不同的协议。

 

#include "sys/types.h"

#include "sys/socket.h"

ssize_t sendto(int sockfd,  const void * buf, size_t len, int flags, const struct sockaddr * to, socklen_t to_len);

返回值 如果成功则返回发送字节数,返回-1出错。

参数buf是要发送的内容,len发送的长度,flags在这里总是为0, to要发送的目的套接口描述结构,to_len指的是to的长度。

 

ssize_t recvfrom(int sockfd, void * buf, size_t len, int flags, struct sockaddr * from, socklen_t * fromlen)

很好理解,稍微不同的地方是from指的是发送者的套接口描述结构。如果你要处理完后,有消息向该套接口发送则建议取出,如果只是取数据,并不对来源发送任何响应,则直接放NULL即可。

 

(注:这个2个函数也可以用于TCP中,用于替代read和write,但一般没有这个必要)。

 

例子就给之前聊天程序用UDP改写下:

[root@liumengli net]# cat chat_udp_server.c

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/wait.h"
#include "sys/select.h"
#include "sys/poll.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        struct sockaddr_in * client_socket = NULL;
        char send[MAXSIZE + 1];
        char recv[MAXSIZE + 1];

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_socket.sin_port = htons(atoi(argv[1]));
        bind(sockfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));
        socklen_t len = sizeof(client_socket);

        for(;;) {
                fd_set rest;
                FD_ZERO(&rest);
                FD_SET(0, &rest);
                FD_SET(sockfd, &rest);
                int flag = select(sockfd + 1,&rest, NULL, NULL, NULL);
                if(flag <= 0)
                        continue;
                if(FD_ISSET(0, &rest) && client_socket) {
                        int n = read(0, send, MAXSIZE);
                        int flag = sendto(sockfd, send, n, 0, (struct sockaddr *)client_socket, sizeof(struct sockaddr_in));
                        if(flag == -1)
                                printf("system message:send failed!\n");
                }

                if(FD_ISSET(sockfd, &rest)) {
                        client_socket = (struct sockaddr_in *) malloc (sizeof(struct sockaddr_in));
                        socklen_t len = sizeof(struct sockaddr_in);//这步一定要有,一定要使len长度确定,不然就会发现无法正确的到客户端信息,如果不需要返回数据给客户端,则无所谓,当然聊天是双方,得不到客户端信息,则没法“聊”下去
                        int n = recvfrom(sockfd, recv, MAXSIZE, 0, (struct sockaddr *)client_socket, &len);
                        recv[n] = '\0';
                        printf("client message:%s", recv);
                }
        }
}

 

[root@liumengli net]# cat chat_udp_client.c
#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/select.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        int maxfdpl;
        char send[MAXSIZE];
        char recv[MAXSIZE];

        if(argc != 2) {
                printf("please input port");
                exit(1);
        }

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_port = htons(atoi(argv[1]));
        inet_pton(AF_INET, "192.168.1.235", &serv_socket.sin_addr);

        for(;;) {
                fd_set rest;
                FD_ZERO(&rest);
                FD_SET(0, &rest);
                FD_SET(sockfd, &rest);
                int flag = select(sockfd + 1, &rest, NULL, NULL, NULL);
                if(flag <= 0)
                        continue;
                if(FD_ISSET(0, &rest)) {
                        int n = read(0, send, MAXSIZE);
                        int temp = sendto(sockfd, send, n, 0, (struct sockaddr *)&serv_socket, sizeof(struct sockaddr_in));
                        if(temp == -1)
                                printf("system message:send failed\n");
                }

                if(FD_ISSET(sockfd, &rest)) {
                        int n = recvfrom(sockfd, recv, MAXSIZE, 0, (struct sockaddr *)NULL, NULL);
                        recv[n] = '\0';
                        printf("server message:%s", recv);
                }
        }
}

 

相对于TCP,UDP的要简单很多。因为UDP没有链接,所有链接带来了很多麻烦在这里就不复存在,首先不用为释放链接烦恼。其次,服务器设计方面要简单,TCP是以链接为基础的传输服务,因此TCP服务器都是并发多进程为每一个链接创立一个线程然后为每一个客户服务。而UDP没有链接,UDP服务器常常采用迭代式设计不需要多进程。(当然,如果你设计成多进程为每一个客户服务,也似可以的,而且会提高效率,当然给自己写代码也带来麻烦)。

 

其次,有点注意,UDP不提供确认。如果在聊天过程中,我们把服务器关了。客户端不关,你仍然会发现客户端不会报任何错误(UDP不提供确认)。如果想提供保证,则需要自己实现。

 

TCP在调用read去读套接口数据时候,如果读到0,一般则意味着对方发送fin包,需要关闭链接。UDP如果调用recvfrom读到0,没有关闭链接一说,所以也不存在所谓的FIN,UDP接受到0则表示数据端内确实没有数据。

分享到:
评论

相关推荐

    104_网络编程基础知识.UDP编程

    【标题】"104_网络编程基础知识.UDP编程"主要涵盖了C#语言在网络编程中的应用,特别是关于UDP(User Datagram Protocol)协议的编程实践。UDP是传输层的一个无连接协议,它提供了一种简单而高效的数据报服务,广泛...

    TCP.UDp.rar_UDP高级编程_tcp.udp

    UDP编程的重点在于如何在没有内置确认机制的情况下实现可靠的数据传输,例如通过自定义的序列号和确认机制。此外,UDP的多播功能允许一次性将数据发送到多个目的地,这对于广播和多用户应用非常有用。 在创建一个...

    tcp[1].udp高级编程

    在IT行业中,网络编程是不可或缺的一部分,而TCP和UDP协议则是网络通信的两大基石。本文将深入探讨"TCP[1].UDP高级编程"这一主题,旨在帮助开发者掌握这两种传输层协议的高级用法,以及如何在实际项目中利用socket...

    TCP.UDP_Advanced_ProgrammingTCP.UDP高级编程

    在UDP编程中,我们关注的是数据报的封装和解封装,以及多播和广播功能的实现。同样在VC++ 6.0下,开发人员需要利用Winsock库,创建UDP套接字,并使用sendto和recvfrom函数进行数据的发送和接收。 客户端和服务端...

    TCP.UDP高级编程

    在IT行业中,网络编程是至关重要的领域,TCP(传输控制协议)和UDP(用户数据报协议)是网络通信中的两大基础协议。TCP以其可靠性和顺序传输而著名,而UDP则以高效、无连接的特点受到青睐。这篇关于"TCP.UDP高级编程...

    TCP.UDP高级编程(含源代码)

    4. **同步与异步**:理解同步和异步I/O模型在TCP/UDP编程中的应用及其优缺点。 这个资源的源代码部分将涵盖以上提到的各个方面,通过阅读和实践,开发者不仅可以掌握TCP和UDP的基本原理,还能了解到在实际项目中...

    UDP-SOCKET-API.rar_BCB6 UDP_Bcb.Udp接收_UDP_bcb 开发 socket

    标签"bcb6_udp bcb.udp接收 udp bcb_开发_socket"进一步明确了这个API主要关注的领域,包括使用BCB6进行UDP接收、UDP相关的开发以及与socket编程相关的内容。 根据压缩包子文件的文件名称"18403834cb6UdpSrc(自已...

    20. 网络编程2UDP编程2.rar

    网络编程2UDP编程2.rar”专注于J2ME(Java 2 Micro Edition)环境下的UDP通信实现,适合于对移动设备和嵌入式系统开发感兴趣的开发者。 J2ME是一种Java平台,主要用于开发运行在移动设备、消费电子设备等小型计算...

    手机游戏开发重要技术资料分享20.网络编程2UDP编程.zip

    手机游戏开发重要技术资料分享20.网络编程2UDP编程.zip

    tcp.udp高级编程

    TCP与UDP编程的一个重要环节是Socket接口,它是操作系统提供的API,用于应用程序与网络服务进行交互。创建Socket,绑定IP地址和端口号,监听连接(TCP),或发送/接收数据(TCP和UDP)是基本操作。在TCP编程中,...

    JAVA进行UDP编程

    下面将详细介绍Java进行UDP编程的相关知识点。 **一、UDP的特点** 1. **无连接性**:UDP不建立连接,直接发送数据,因此速度快,但可能会丢失数据或顺序错乱。 2. **不可靠性**:UDP不保证数据包的接收,也不检测和...

    SteamVR.OpenTrack.UDP_steamvr_源码

    4. UDP网络编程:理解UDP协议的特性和限制,编写UDP客户端和服务器程序,处理数据包的发送和接收。 5. 实时数据处理:了解如何高效地处理和传输实时数据,保证追踪的准确性和流畅性。 对于想要深入研究VR追踪系统...

    20. 网络编程2UDP编程1.rar

    本教程主要关注的是J2ME(Java Micro Edition)环境下的网络编程,特别是针对UDP(User Datagram Protocol)的编程。J2ME是Java平台的一个子集,专为资源有限的设备如移动电话和嵌入式系统设计,它提供了在这些设备...

    TCP.UDP_gaojibiancheng.rar_TCP-UDP_c# tcp/udp_tcp/udp_visual c

    3. **UDP编程基础**:介绍UDP的无连接特性和数据报的发送与接收,包括C#中的UdpClient类和Visual C++中的sendto和recvfrom函数。 4. **并发处理**:如何在TCP和UDP中处理多个并发连接,包括线程池、异步编程模型...

    TCP UDP高级编程:一个VC++服务端程序 (1).rar

    在IT行业中,网络编程是至关重要的领域,尤其是TCP和UDP协议,它们构成了互联网通信的基础。本文将深入探讨TCP和UDP的高级编程,并结合VC++这一强大的C++开发环境,为初学者提供一个实用的服务端程序示例。 TCP...

    TCP.UDP_jt.rar_DELPHI7 UDP_UDP delphi_jt_实时

    在Delphi7中,Indy 和 Winsock 组件同样可以用于UDP编程。UDP适用于实时性要求高的场景,例如在线游戏、视频会议、网络广播等。 "TCP.UDP协议的实时监听"可能是指实现一个可以同时监听TCP和UDP连接的服务端程序。在...

    Udp编程:服务器和客户端

    在本项目中,"Udp编程:服务器和客户端"是通过Visual C++6.0环境,使用C++语言实现的UDP通信示例。下面我们将深入探讨UDP服务器和客户端的编程原理及其关键知识点。 1. UDP协议基础: - UDP协议的特点在于其轻量级...

    UDP.rar_c#的UDP编程_site:www.pudn.com

    UDP(User Datagram Protocol)是互联网协议族中的一种无连接、不可靠的传输协议,与TCP相比,它更轻量级,适用于对实时性..."第06章 UDP应用编程.ppt"文件应详细讲解了这些内容,建议仔细研读,加深对UDP编程的理解。

    TCP/UDP编程总结

    通过阅读TCP UDP笔记.doc,深入理解TCP连接与断开过程.pdf中的细节,以及TCP与UDP编程步骤.pdf的实践指导,初学者可以逐步构建起完整的TCP/UDP编程能力。在实际项目中,灵活运用这些知识,可以有效地处理各种网络...

Global site tag (gtag.js) - Google Analytics