Linux--网络编程(二)UDP编程

76 篇文章 5 订阅

UDP编程

 数据报通信;对于数据报通信的服务器端来说,它不必再在一个端口上侦听,以等待建立连接,而只需生成一个端口描述符,并且把这个端口描述符绑定到本地地址上就可以了。


UDP网络编程具体的操作流程为:
这里写图片描述


socket()

 使用系统调用socket()来获得文件描述符,该调用的声明格式为:

#include <sys/types.h>
#include <sys/socket.h>
int socket<int damain, int type, int protocol);

socket函数说明

这里写图片描述


bind()

 一旦有了一个套接口以后,下一步工作就是把套接口绑定到本地计算机的某一个端口上,但如果只想使用connect()则没有这个必要了。
 下面是系统调用bind()的定义:

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

bind函数说明

这里写图片描述


connect()

 connect()系统调用由客户端调用,它的用法如下:

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,struct sockaddr *serv_addr, int addrlen);

connect函数说明

这里写图片描述


sendto()和recvfrom()

 因为数据报套接口是无连接的,它并不连接到远程的主机上,所以在发送数据报之前,必须首先给出目的地址:
 这两个函数定义如下:

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

sendto函数说明

这里写图片描述

recvfrom函数说明

这里写图片描述


close()和shutdown()

 可以使用close()调用关闭连接的套接口文件描述符,它的调用方式为:

close(sockfd);
//这样以后就不能再对此套接口进行任何的读/写操作了。
//使用系统调用shutdown(),可有更多的控制权
int shutdown(int sockfd, int how);

int shutdown(int sockfd, int how)

  • 第一个参数是希望切断通信的套接口文件描述符。
  • 第二个参数how的值如下
    • 0:不允许再接收数据
    • 1:不允许再发送数据
    • 2:发送和接收数据都不允许
    • shutdown()调用成功的返回值为0,如果失败则返回-1

udp服务器端的程序:

/*udpserver.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>

#define SERVER_PORT 8888//绑定端口
#define MAX_MSG_SIZE 1024//数据最大字节为1024

void udps_respon(int sockfd){
        struct sockaddr_in addr;
        int addrlen,n;
        char msg[MAX_MSG_SIZE];
        while(1){
                /*等待数据请求*/
                n = recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr*)&addr,&addrlen);
                msg[n] = 0;
                /*显示服务器已经收到了信息*/
                fprintf(stdout, "I have received:%s\n", msg);
                fprintf(stdout, "Client Port:%d\n",ntohs(addr.sin_port));
                sendto(sockfd,msg,n,0,(struct sockaddr*)&addr,addrlen);
        }
}

int main(void){
        int sockfd;//定义一个socket描述符
        struct sockaddr_in addr;

        sockfd = socket(AF_INET,SOCK_DGRAM,0);//给这个描述符赋值

        if(sockfd<0){//socket没有收到数据
                fprintf(stderr, "Socket Error:%s\n",strerror(errno));
                exit(1);
        }
        bzero(&addr,sizeof(struct sockaddr_in));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = htons(SERVER_PORT);

        if(bind(sockfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in))<0)
        {
                fprintf(stderr, "Bind Error%s\n",strerror(errno));
                exit(1);
        }
        udps_respon(sockfd);
        close(sockfd);
}

udp客户端的程序:

/*客户端程序UDPClient.c,使用方法UDPClient ServerIP ServerPort*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#define MAX_BUF_SIZE 1024

void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len){
    char buffer[MAX_BUF_SIZE];
    int n;
    while(1){

         printf("please input message:");
        /*从键盘读入,写到服务端*/
        scanf("%s",buffer);
        //fgets(buffer,MAX_BUF_SIZE,stdin);
        printf("input %s,len=%d\n",buffer,strlen(buffer));
        //sendto(sockfd,buffer,strlen(buffer),0,addr,len);
        sendto(sockfd,buffer,strlen(buffer),0,addr,len);
        bzero(buffer,MAX_BUF_SIZE);

        /*从网络上读,写到屏幕上*/
        n = recvfrom(sockfd,buffer,MAX_BUF_SIZE,0,NULL,NULL);
        buffer[n] = 0;
        printf("I have received:%s,len=%d\n",buffer,n );
        //fputs(buffer,stdout);

    }
}

int main(int argc,char **argv){
    int sockfd,port;
    struct sockaddr_in addr;
    if(argc != 3){
        fprintf(stderr, "Usage:%sserver_ip server_port\n",argv[0]);
        exit(1);
    }
    if((port = atoi(argv[2]))<0){
        fprintf(stderr, "Usage:%sserver_ip server_port\n",argv[0]);
        exit(1);
    }

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0){
        fprintf(stderr, "Socket Error:%s\n",strerror(errno));
        exit(1);
    }

    /*填充服务端的资料*/
    bzero(&addr,sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    if(inet_aton(argv[1],&addr.sin_addr)<0){
        fprintf(stderr, "IP error:%s\n", strerror(errno));
        exit(1);
    }
    udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in));
    close(sockfd);
}

————————————————————-

后记:

在Linux上运行,我的服务器是CentOS无图形化界面的:

  • vim udpserver.c 粘贴保存
  • vim udpclient.c 粘贴保存
  • gcc -o udpserver udpserver.c 编译命令 :gcc -o 生成文件名 欲编译文件名
  • gcc -o udpclient udpclient.c 编译命令 :gcc -o 生成文件名 欲编译文件名
  • ./udpserver 运行命令
  • ./udpclient 127.0.0.1 8888 运行命令:./运行文件名 服务器地址 服务器端口
  • 测试
  • Ctrl + “C”关闭程序

测试

在客户端输入:“123456789”

这里写图片描述

服务器端显示:“123456789”
这里写图片描述

电脑端打开TCP/UDP测试软件输入:“987654321”

这里写图片描述

服务器端显示:“987654321”

这里写图片描述

完美!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值