网络基础1

目录

一.协议分层 

二.局域网 

三.网络编程套接字

1.ip地址,端口号(port)

2.一个端口号可以和多个进程关联?  x

3.TCP协议,UDP协议

4.网络字节序

 5.网络编程,socket是有很多类别

6.sockaddr结构

四.网络编程


一.协议分层 

二.局域网 

三.网络编程套接字

1.ip地址,端口号(port)

ip地址用来标识互联网中唯一的一台主机;

端口号用来标识该指定机器的唯一进程。

[ip, 端口号](套接字,socket):互联网中唯一的两个进程

2.一个端口号可以和多个进程关联?  x

一个进程可以和多个端口号关联?   √

3.TCP协议,UDP协议

TCP:可靠通信,如果中途数据出问题,会做出调整(做更多工作)

UDP:不管有没有出问题,正常发送(速度快)

4.网络字节序

机器发出的数据----a--->网络-----b--->目标机器接收

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。
例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;
如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。



 

 5.网络编程,socket是有很多类别

unix socket:域间socket,同一台机器上的文件路径,命名管道,本主机内部通信。

网络socket:ip + port(端口号),网络通信。

原始socket:编写一些网络工具

6.sockaddr结构

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


 

四.网络编程

UdpServer.hpp

#pragma once

#include<iostream>
#include<string>
#include<strings.h>
#include<string.h>

#include <sys/types.h>          
#include <sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#include"nocopy.hpp"
#include"Comm.hpp"


const static int defaultsize = 1024;
 
class UdpServer
{
public:
    UdpServer(const std::string& ip, const uint16_t port)
        :_ip(ip)
        ,_port(port)
    {

    }
    void Init()
    {
        //1.创建socket,创建文件细节
        sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 参数1.协议家族(AF_UNIX, AF_INET)   参数2.套接字类型   返回值:文件描述符
        if(sockfd < 0)//创建失败
        {
            std::cout << "sockfd error" << std::endl;
            exit(Socket_Err);
        }
        std::cout << "sock success" << std::endl;

        //2.bind绑定指定网络信息
        struct sockaddr_in local;  //网络socket结构体    //内含服务端server的一些信息
        bzero(&local, sizeof(local));  //同memset(&local, 0, sizeof(local))
        local.sin_family = AF_INET;  //协议家族,进行网络通信
        local.sin_port = htons(_port);  //端口号,htons将主机序列转化位网络序列
        local.sin_addr.s_addr = INADDR_ANY;   //存的是ip,我们不希望服务端绑定固定ip,采取INADDR_ANY任意绑定ip
        int n = bind(sockfd, (struct sockaddr*)&local, sizeof(local));  //将进程绑定端口号
        if(n != 0)
        {
            std::cout << "bind fail" << std::endl;
            exit(Bind_Err);
        }
    }
    void Start()
    {
        char buffer[defaultsize];
        for(;;) //服务器永不退出
        {
            struct sockaddr_in peer; //客户端
            socklen_t len = sizeof(peer);  //不能乱写
            ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&peer, &len);  //收信息,给我们客户端的socket信息
            if(n > 0) //成功
            {
                buffer[n] = 0;
                std::cout << "client say:" << buffer << std::endl;

                sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr*)&peer, len);  //发信息
            }
        }
    }

    ~UdpServer()
    {}
private:
    std::string _ip;
    uint16_t _port;
    int sockfd;
};

Main.cc


#include"UdpServer.hpp"
#include<memory>


void Usage(std::string proc)
{
    std::cout << "Usage: \n\t" << "local_ip local_port\n" << std::endl;
}

//   ./udq_server 127.0.0.1 8888   
//127.0.0.1:本地环回,通常用来进行网络OS的测试
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        return Usage_Err;
    }
    std::string ip = argv[1];
    uint16_t port = std::stoi(argv[2]);
    std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(ip, port);
    usvr->Init();
    usvr->Start();
    return 0;
}

Comm.hpp

#pragma once

enum
{
    Usage_Err = 1,
    Socket_Err,
    Bind_Err
};

nocopy.hpp

#pragma once

#include<iostream>

class nocopy
{
public:
    nocopy(){}
    nocopy(const nocopy&) = delete;
    const nocopy& operator=(const nocopy&) = delete;
    ~nocopy(){}
};

 udpclient.cc

#include<iostream>
#include<string>
#include<cstring>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <unistd.h>

void Usage(const std::string& process)
{
    std::cout << "Usage:" << process << "server ip" << " " << "server port" << std::endl;
}

//  ./udp_client serverip  serverport这样运行
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        return 1;
    }

    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);
    //1.创建socket
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0)
    {
        std::cerr << "socket error" << strerror(errno) << std::endl;
        return 1;
    }
    //2.client需要bind,但我们不需要显示bind,让本地OS自动随机bind,选择随机端口号
    //2.1填充server信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());

    while(true)
    {
        std::string inbuffer;
        std::cout << "Please say#";
        getline(std::cin, inbuffer);

        ssize_t n = sendto(sock, inbuffer.c_str(), sizeof(inbuffer), 0, (struct sockaddr*)&server, sizeof(server)); //发给server
        //send时,随机bind端口号
        if(n > 0)
        {
            char buffer[1024];
            struct sockaddr_in temp;
            socklen_t len = sizeof(temp);

            ssize_t m = recvfrom(sock, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&temp, &len);  //收server信息
            if(m > 0)
            {
                buffer[m] = 0;
                std::cout << "server echo#" << buffer << std::endl;
            }
            else break;
        }
        else
        {
            break;
        }
    }

    close(sock);
    return 0;
}

makefile 

.PHONY:all
all:udp_server udp_client

udp_server:Main.cc
	g++ -o $@ $^ -std=c++14
udp_client:udpclient.cc
	g++ -o $@ $^ -std=c++14

.PHONY:clean
clean:
	rm -rf udp_server udp_client

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值