波奇学Linux:网络套接字

domain:ipv4 还是ipv6

type:面向字节流还是...

虚拟机

云服务器禁止直接bind公网ip

服务器可以有多个ip,如果只绑定一个ip,只能收到来自一个ip的信息

任意地址绑定

关于port的问题

[0,1024]:系统内定的端口号,一般要用固定的应用层协议,http:80 err string : Permission denied

网络通信时,顾客端通信往往要指定端口号,一般ip地址和端口号会被封装成网站的形式

UdpClient.cc

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

void Usage(std::string proc)
{
    std::cout << "\n\rUsage: " << proc << " serverip serverport\n"
              << std::endl;
}
// int argc表参数数量, argv是参数内容
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        Usage(argv[0]);
        exit(0);
    }
    // 获取目标ip
    std::string serverip=argv[1];
    uint16_t serverport=std::stoi(argv[2]);

    struct sockaddr_in server;
    //将server的内容置空
    bzero(&server,sizeof(server));
    //套间字类型
    server.sin_family=AF_INET;
    //端口
    server.sin_port=htons(serverport);
    //ip地址
    server.sin_addr.s_addr=inet_addr(serverip.c_str());
    socklen_t len=sizeof(server);
    //SOCK_DGRAM 表示 udp ,AF_INET 表示网落通信
    // 像是创建网卡文件返回文件的描述符
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        cout<<"socker error"<<endl;
        return 1;
    }
    // client 也要绑定,有自己的ip和端口
    // 不需要自己绑定,让os自由随机选择
    //系统什么时候绑定的? 首次发送数据时
    string message;
    char buffer[1024];
    while(true)
    {
        cout<<"Please Enter@";
        std::getline(cin,message);
        std::cout<<"client sent message: "<<message.c_str()<<std::endl;
        //从网卡文件中发送信息
        sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);
        // 从网卡文件中获取信息
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);
        if(s > 0)
        {
            buffer[s] = 0;
            cout << buffer << endl;
        }
    }
    close(sockfd);
    return 0;
}

udpServer.hpp

#pragma once
#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<cstdlib>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <functional>
#include<unistd.h>
// using func_t = std::function<std::string(const std::string&)>;
typedef std::function<std::string(const std::string&)> func_t;
uint16_t defaultport=8089;
std::string defaultip="0.0.0.0";
#define Size 1024
class UdpServer
{
public:
    UdpServer(const uint16_t &port=defaultport,const std::string &ip=defaultip)
    :sockfd_(0)
    ,port_(port)
    ,ip_(ip)
    ,isrunning_(false)
    {}
    void Init()
    {
        //创建网络文件
        sockfd_=socket(AF_INET,SOCK_DGRAM,0);
        if(sockfd_<0)
        {
            printf("socket creaate error");
            exit(1);
        }
        // bind socket 绑定网络文件
        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        local.sin_family=AF_INET;//表明网络类型
        local.sin_port=htons(port_); //端口号是来回发送的 htons保证端口号是网络字节序列->大端
        local.sin_addr.s_addr=inet_addr(ip_.c_str()); //string->uint32_t ip也是来回发送的 也要转为网络字节序列->大端
        
        int n=bind(sockfd_,(const struct sockaddr *)&local,sizeof(local));
        if(n<0)
        {
            printf("bind error");
        }
    }
    void Run(func_t func)
    {
        isrunning_=true;
        char inbuffer[Size];
        while(isrunning_)
        {
            struct sockaddr_in client;
            socklen_t len=sizeof(client);
            //接收信息
            ssize_t n=recvfrom(sockfd_,inbuffer,sizeof(inbuffer)-1,0,(struct sockaddr*)&client,&len);
            if(n<0)
            {
                printf("recvfrom error");
            }
            inbuffer[n]=0;
            std::cout<<"receive message: "<<inbuffer<<std::endl;
            std::string echo_string = inbuffer;
            // std::string echo_string = func(info);
            sendto(sockfd_,echo_string.c_str(),echo_string.size(),0,(const sockaddr*)&client,len);
        }
    }
    ~UdpServer()
    {
         if(sockfd_>0) close(sockfd_);
    }
private:
    int sockfd_; //网络文件描述符
    uint16_t port_; //服务器端口号
    std::string ip_;
    bool isrunning_;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值