简单的UDP网络编程——socket相关

——————sockaddr结构

socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6等,然而各种网络协议的地址格式格式并不同

虽然socket api的接口是sockaddr,但是我们真正在基于IPv4编程时,使用的数据结构是sockaddr_in,这个结构主要有三部分信息:地址列席、端口号、IP地址
————————————————————

简单的UDP网络程序

回显服务器(Echo Server)
客户端——————————
1、从标准输入中读取用户输入;
2、把这个字符串通过socket传递给服务器;
3、尝试从服务器读取数据;
4、把从服务器读取到的数据显示到标准输出上。
服务器————————————
1、尝试从socket中读取数据(进行一系列的计算)
2、把这个字符串原封不动的写回给客户端。
UDP服务器

#include<stdio.h>                                                                          
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>

//./server 192.168.80.132 9090
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        printf("Usage ./server [ip] [port]\n");
        return 1;
    }
    int fd = socket(AF_INET,SOCK_DGRAM,0);
    if(fd < 0)
    {
        perror("socket");
        return 1;
    }
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));
    int ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
    if(ret < 0)
    {
        perror("bind");
        return 1;
    }
    while(1)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        char buf[1024] = {0};
        ssize_t read_size = recvfrom(fd,buf,sizeof(buf) - 1,0,(struct sockaddr*)&peer,&len);
        if(read_size < 0)
        {
            //filure
            perror("recvfrom");
            continue;
        }
        buf[read_size] = "\0";
        printf("client say:%s\n",buf);
        sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&peer,len);
    }
    close(fd);
    return 0;
}

*——socket的参数使用SOCK_DGRAM表示UDP;
*——bind之后就可以直接进行通信了;
*——使用sendto和recvfrom来进行数据读写。

UDP客户端

#include<stdio.h>                                                                                 
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>

//.client 127.0.01 9090
int main(int argc,char *argv[])
{
     if(argc != 3)
     {
         printf("usage /client[ip][port]\n");
         return 1;
     }
     int fd=socket(AF_INET,SOCK_DGRAM,0);
     if(fd<0){
         perror("socket");
         return 1 ;
     }
     struct sockaddr_in server_addr;
     server_addr.sin_family = AF_INET;
     server_addr.sin_addr.s_addr = inet_addr(argv[1]);
     server_addr.sin_port = htons(atoi(argv[2]));
     while(1)
     {
        char buf[1024]={0};
        ssize_t read_size = read(0,buf,sizeof(buf)-1);
        if(read_size<0){
          perror("read");
          return 1;
        }
        if(read_size==0){
             printf("read done!\n");
             return 0;
         }
       buf[read_size]='\0'
           ;
       sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&server_addr,sizeof(server_addr));
       char buf_output[1024]={0};
       read_size = recvfrom(fd,buf_output,sizeof(buf_output)-1,0,NULL,NULL);
       if(read_size<0){
             perror("recvfrom");
             return 1;
        }
       buf_output[read_size]='\0';
       printf("server resp:%s\n",buf_output);
    }
     close(fd);
     return 0;                                                                                    
}

*——bind之后就可以直接进行通信了;
*——使用sendto和recvfrom来进行数据读写。

客户端一般不用绑定端口号:
由于客户端的机器装了哪些程序不确定,如果强行绑定端口号,就有可能和客户端的其他程序冲突,如果不绑定,操作系统就会在通信时自动分配一个端口号。

猜你喜欢

转载自blog.csdn.net/paranoid_cc/article/details/80311138