Linux网络编程基础(二)

来源:互联网 发布:js 全局变量 丢失属性 编辑:程序博客网 时间:2024/06/05 09:05
  前面讲了TCP的编程流程,这里接着来讲UDP的编程流程。讲完UDP的编程流程然后再说两者的区别。

UDP的编程流程:同样也要分为服务器端和客户端。
1、服务器端,如下图:
这里写图片述
2、客户端,如下图:
这里写图片描述
现在描述一下UDP编程的接收和发送消息的系统调用函数recv from()和send to():

#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);/*recvfrom读取sockfd上的数据,buf和len参数分别指定读缓冲区的位置和大小。因为UDP是无连接通信,所以我们每次读取数据都需要获取发送端的socket地址,即参数src_addr所指的地址,addrlen参数则指定该地址的长度。*/ssize_t sendto(int sockfd,const void* buf,size_t len,int flags,          const struct sockaddr* dest_addr,socklen_t addrlen);/*sendto往sockfd上写入数据,buf和len参数分别指定写缓冲区的位置和大小,dest_addr参数指定接收端的socket地址,addrlen参数则指定该地址的长度。*/
   recvfrom/sendto系统调用也可以用于面向连接的socket的数据读写,只需把最后两个参数设置为NULL以忽略发送端/接收端的socket地址。

2、流式服务(TCP)和数据报服务(UDP)的区别
此处引用一本书里图作以说明
这里写图片描述

注:
(1) TCP接收缓冲区会对接收到的TCP报文进行重排、整理再交付给应用层,即流
式服务 sebd() n次 recv() 一次;
(2) 数据报服务具有“不可靠”的特点,需要上层协议来处理数据和超时重传。

3、UDP编程举例
服务器端ser.c

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>#include<unistd.h>#include<sys/socket.h>#include<sys/types.h>#include<arpa/inet.h>void main(){    int sockfd = socket(AF_INET,SOCK_DGRAM,0);    assert(sockfd != -1);    struct sockaddr_in ser,cli;    ser.sin_family = AF_INET;    ser.sin_port = htons(6000);    ser.sin_addr.s_addr = inet_addr("127.0.0.1");    int res = bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));    assert(res != -1);    while(1)    {        char buf[128] = {0};        int len = sizeof(cli);        recvfrom(sockfd,buf,127,0,(struct sockaddr*)&cli,&len);        printf("ip::%s\nport::%d\ndata::%s\n",                inet_ntoa(cli.sin_addr),                ntohs(cli.sin_port),buf);        sendto(sockfd,"I know",strlen("I know"),0,                (struct sockaddr*)&cli,len);    }    close(sockfd);}

客户端 cli.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>void main(){    int sockfd = socket(AF_INET,SOCK_DGRAM,0);    assert(sockfd != -1);    struct sockaddr_in ser,cli;    ser.sin_family = AF_INET;    ser.sin_port = htons(6000);    ser.sin_addr.s_addr = inet_addr("127.0.0.1");    sendto(sockfd,"heelo world",11,0,        (struct sockaddr*)&ser,sizeof(ser));    char buf[128] = {0};    recvfrom(sockfd,buf,127,0,NULL,NULL);    printf("OK\n");    close(sockfd);}
原创粉丝点击