LINUX网络编程:UdpSocket echo服务器

目录

1.接口

1.1 socket

1.2bind

2.实现

2.1server


echo服务器:将收到的消息回显到客户端。

主要目的:学习网络系统调用接口的使用,和一些网络基础知识

1.接口

1.1 socket

#include <sys/types.h>    
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

//创建套接字 成功返回文件描述符,失败返回-1

domain:选择网络通信的协议族,也叫域,决定了socket在什么网络下通信

type:指定套接字的类型,SOCK_STREAM面相数据流,SOCK_DGRAM面相数据报。

protocol:填好前两个参数,置为零即可

1.2bind

#include <sys/types.h>         
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

//将创建好的套接字与网络绑定起来(IP, port)

绑定成功返回 0 失败返回-1

sockfd:socket返回的文件描述符

addr:Socket编程中用于表示地址的通用结构体,它定义了一个通用的地址格式,这里玩了一个多态,sockaddr可以接收sockaddr_in,sockaddr_un传参的时候需要强转为sockaddr,在传参之前,sockaddr_in前三个字段都是要被填充的,其他也一样。

addrlen:参数2的大小

2.实现

2.1server

#pragma once
#include <iostream>
#include <string>
#include "log.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
enum
{
    SocketError = 1,
    BindError = 2,
    usageError = 3,
};

class Udpserver
{
public:
    Udpserver(uint16_t port)
        : _port(port), _isrunning(false), _socketfd(0)
    {}

    void init()
    {
        _socketfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_socketfd < 0)
        {
            Log(FATAL, "Socket Error: ,%s errno:%d", strerror(errno), errno);
            exit(SocketError);
        }
        //创建socket成功
        Log(Info,"Socker Success _Socketfd:%d", _socketfd);

        //开始绑定
        //将创建好套接字,与网络关联起来。
        struct sockaddr_in local;
        bzero(&local,sizeof(local));//必须置为0否则会段错误
        local.sin_family = AF_INET;//绑定协议族
        local.sin_port = htons(_port); //网络是大端,需要转换
        //in_addr_t  tmp = inet_addr("127.0.0.1"); //将字符串转化为uint_32 ip && 转化为大端
        // local.sin_addr.s_addr = tmp;

        local.sin_addr.s_addr = INADDR_ANY;//绑定任意IP,不建议绑定确定的ip
                                           //一台主机有很多种IP,一旦绑定确定的某个IP,使用其他种的IP就不能访问到服务器
        int n = bind(_socketfd, (struct sockaddr*)&local, sizeof(local));
        if(n < 0)
        {
             Log(FATAL, "Bind Errorr: ,%s errno:%d", strerror(errno), errno);
             exit(BindError);
        }
        Log(Info,"Bind Success");
    }

    void start()
    {
        _isrunning = true;
        while(true)
        {
          char buffer[1024];
          struct sockaddr_in peer;
          bzero(&peer,sizeof(buffer));
          socklen_t addrlen = sizeof(peer);//既是输入型参数,也是输出型参数,必须初始化 
          ssize_t n = recvfrom(_socketfd, buffer, sizeof(buffer)-1, 0,(struct sockaddr*)&peer, &addrlen);

          if(n > 0) //读取数据成功
          {
            buffer[n] = 0;
            Log(Info, "[get message:%s]\n",buffer);
            //将消息重新发送回去
            sendto(_socketfd, buffer, sizeof(buffer)-1, 0,(struct sockaddr*)&peer, addrlen);
          }  
        }
        _isrunning = false;

    }

private:
    uint16_t _port;  // 端口号
    int _socketfd;   // socket返回的文件描述符
    bool _isrunning;  //服务器是否运行
};

注意:

1.绑定ip的时候要使用INADDR_ANY,这样使用这台主机的任意一个ip都可以访问服务器

2.电脑分为小端机和大端机,但是在网络中只有大端,所以端口号和ip都要转化为大端。

3.客户端不用显示的绑定,端口号会自动分配,防止冲突,就会出现打开京东就打不开淘宝的问题。

           

     

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值