基本UDP套接字编程

UDP是无连接不可靠的数据报协议,非常不同于TCP提供的面向连接的可靠字节流。然而相比于TCP,有些场合更适合使用UDP,使用UDP的一些常见应用程序有:

DNS,NFS和SNMP。借用linux一站式编程里的图:

一、基本套接字函数

udp所用函数:

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, 
                 struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
               const struct sockaddr *to, socklen_t addrlen);
参数说明:

1. 需要说明的是recvfrom的struct sockaddr参数,这是一个值-结果传递,返回时填入收到的udp数据包的来源,并不是只接受某个主机的数据包

其他的参数很容易理解。

简单的udp服务器程序如下:

 #include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#define    SERV_PORT         8000    /* TCP and UDP */
#define    MAXLINE        4096    /* max text line length */
int main(void)
{
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int sockfd;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int i, n;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    bzero(&servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
    perror("bind error: ");
    exit(0);
    }
    printf("Accepting connections ...\n");
    while (1) {
    cliaddr_len = sizeof(cliaddr);
    n = recvfrom(sockfd, buf, MAXLINE, 0, (struct sockaddr *) &cliaddr,
             &cliaddr_len);
    if (n == -1) {
        perror("recvfrom error");
        exit(0);
    };
    printf("received from %s at PORT %d\n",
           inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
           ntohs(cliaddr.sin_port));
    for (i = 0; i < n; i++) {
        buf[i] = toupper(buf[i]);
    }
    n = sendto(sockfd, buf, n, 0, (struct sockaddr *) &cliaddr,
           sizeof(cliaddr));
    if (n == -1) {
        perror("sendto error");
        exit(0);
    }
        bzero(buf,sizeof(buf));
    }
}
上面程序使用基本的udp的socket函数,来接收客户端发送的字符,然后转换为大写,回送回去。。。

客户端程序:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define	SERV_PORT		 8000	/* TCP and UDP */
#define	MAXLINE		4096	/* max text line length */
int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    socklen_t servaddr_len;
    char buf[MAXLINE];
   // char recvline[MAXLINE];
    int sockfd, n;
    
    if (argc != 2) {
        perror("usage : tcpcli <ipaddress>");
        exit(0);
    }
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
    
    while(fgets(buf, MAXLINE, stdin) != NULL){
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if(n == -1){
            perror("client sendto error: ");
            exit(0);
        }
        n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, NULL);
        if(n == -1){
            perror("client recive error: ");
            exit(0);
        }
        buf[n] = 0;
        fputs(buf,stdout);     
    }
}
客户端程序很容易理解,只是从标准输入读入数据然后发送到udp套接字。

运行结果:

zal@zal:~/NetBeansProjects/6-17$ ./udpcli 127.0.0.1
asd
ASD
asd
ASD
fd
FD
gfd
GFD
gf
GF

二、UDP的conect函数

udp程序使用conect函数,用来与确定的唯一对端进行通信,只是指定对端的地址信息,并不像tcp那样连接,不会到协议栈底层去,调用conect的通常是UDP客户端程序。与普通UDP区别:

1。不能使用sentto和resvfrom指定目的地址和端口号,改用write、sent、read、recv、recvmsg

2。由已经连接的(假连接)UDP套接字引发的异步错误返回给进程,而未连接的UDP不接受任何异步错误。

3。每次调用sendto都需要将目的地址拷贝到内核,对于已经连接的udp,只需要拷贝一次。效率高。。。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值