UDP - modelo C/S

        Dado que UDP no necesita mantener conexiones, la lógica del programa es mucho más simple, pero el protocolo UDP no es confiable y el mecanismo para garantizar la confiabilidad de la comunicación debe implementarse en la capa de aplicación.

función de comunicación

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

parámetro:

        calcetín: enchufe

        buf: dirección del búfer

        len: tamaño del búfer

        banderas: 0

        src_addr: (struct sockaddr *)&dirección saliente. Estructura de direcciones de pares

        addrlen: entrante y saliente.

valor de retorno:

        Éxito: número de bytes de datos recibidos.

        Fallo: -1 error.

        0: el par está cerrado. 

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

parámetro: 

        calcetín: enchufe

        buf: buffer para almacenar datos

        len: longitud de datos

        banderas: 0

        src_addr: (struct sockaddr *)&addr pasado. estructura de dirección de destino

        addrlen: longitud de la estructura de direcciones.

valor de retorno:

        Éxito: se escribe el número de bytes de datos.

        Fallo: -1, error    

Proceso de implementación de comunicación UDP

/* 编程模型 */
Server							Client
创建套接字(socket)				创建套接字(socket)
准备地址(本机地址sockaddr_in)	准备地址(目标机地址sockaddr_in)
绑定(bind(sockfd+addr))			.....
接受请求(recvfrom)				发送请求(sendto)
响应请求(sendto)					接受请求(recvfrom)
关闭套接字(close)				关闭套接字(close)

Implementación del código del lado del servidor

  • Descripción de los pasos del algoritmo del lado del servidor UDP

        ① Llame a la función socket() para crear un socket sin conexión del lado del servidor.

        ② Llame a la función bind() para vincular el socket a una dirección de punto final disponible de la máquina local.

        ③ Llame a la función recvfrom () para recibir datos del cliente remoto desde el socket y almacenarlos en el búfer. Al mismo tiempo, obtenga la dirección del punto final del socket del cliente remoto y guárdela.

        ④ Según la dirección del punto final del socket guardada del cliente remoto, llame a la función sendto() para enviar los datos en el búfer desde el socket al cliente remoto.

        ⑤ Después de interactuar con el cliente, llame a la función close () para cerrar el socket y liberar los recursos ocupados del sistema.

Aviso:

  1. Sin aceptar, no es necesario establecer una conexión;        
  2. Use recvfrom en lugar de read. El error devuelve -1, el éxito devuelve - el número de bytes leídos del búfer del núcleo.        
  3. Utilice sendto en lugar de escribir. El error devuelve -1, el éxito devuelve - el número de bytes escritos en el búfer del núcleo.
/*server.c*/
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>

#define SERV_PORT 8000

int main(void)
{
    struct sockaddr_in serv_addr, clie_addr;
    socklen_t clie_addr_len;
    int sockfd;
    char buf[BUFSIZ];
    char str[INET_ADDRSTRLEN];
    int i, n;


    /* 打开一个网络通讯端口,分配一个文件描述符sockfd */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&serv_addr, sizeof(serv_addr)); //初始化为空
    serv_addr.sin_family = AF_INET; //地址采用IPv4地址
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //地址从主机字节顺序转换成网络字节顺序
    serv_addr.sin_port = htons(SERV_PORT); //端口号从主机字节顺序转换成网络字节顺序

    /* 将文件描述符sockfd和服务器地址绑定 */
    bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    printf("Accepting connections ...\n");
    while (1) {
         /* 接收client端传过来的的字符串,写入buf */
        clie_addr_len = sizeof(clie_addr);
        n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len);
        if (n == -1)
            perror("recvfrom error");
        
        /* 打印客户端IP及端口 */
        printf("received from %s at PORT %d\n",
                inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
                ntohs(clie_addr.sin_port));

        /* 小写转为大写 */        
        for (i = 0; i < n; i++)
            buf[i] = toupper(buf[i]);

        /* 把数据发送给客户端 */
        n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
        if (n == -1)
            perror("sendto error");
    }

    close(sockfd);

    return 0;
}

Implementación del código del cliente

  •  Descripción de los pasos del algoritmo del cliente UDP

        ① Llame a la función socket() para crear un socket sin conexión del lado del cliente.

        ② Busque la dirección IP y el número de puerto de protocolo del servidor remoto con el que desea comunicarse; luego llame a la función sendto() para enviar los datos en el búfer desde el socket al servidor remoto.

        ③ Llame a la función recvfrom () para recibir datos del servidor remoto desde el socket y almacenarlos en el búfer.

        ④ Después de interactuar con el servidor, llame a la función close () para cerrar el socket y liberar los recursos ocupados del sistema.

Aviso:

  1. No hay conexión, no es necesario establecer una conexión;        
  2. Utilice sendto en lugar de escribir. El error devuelve -1, el éxito devuelve - el número de bytes escritos en el búfer del núcleo.        
  3. Use recvfrom en lugar de read. El error devuelve -1, el éxito devuelve - el número de bytes leídos del búfer del núcleo.
/*client.c*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>

#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    int sockfd, n;
    char buf[BUFSIZ];

    /* 打开一个网络通讯端口,分配一个文件描述符sockfd */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr)); //初始化为空
    servaddr.sin_family = AF_INET; //地址采用IPv4地址
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); //将“点分十进制” -> “二进制整数”
    servaddr.sin_port = htons(SERV_PORT); //端口号从主机字节顺序转换成网络字节顺序

    //bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while (fgets(buf, BUFSIZ, stdin) != NULL) {
        /* 发送给服务端 */
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        if (n == -1)
            perror("sendto error");
        
        /* 从服务端接收数据 */
        n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0);         //NULL:不关心对端信息
        if (n == -1)
            perror("recvfrom error");
        
        /* 输出服务器处理后的数据 */
        write(STDOUT_FILENO, buf, n);
    }

    close(sockfd);

    return 0;
}

 

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43200943/article/details/130238209
Recomendado
Clasificación