网络编程基础概念:
ip地址和端口号
ip地址是网络协议地址(4字节32位,形式:xxx.xxx.xxx.xxx xxx在范围[0, 255]内),是IP协议提供的一种统一的地址格式,每台主机的ip地址不同,一个主机可以有多个ip地址,一个ip地址只能被一个主机占用。
仅使用主机的ip地址就可以实现两主机中不同的应用进程进行网络通信吗?不可以。ip地址只是锁定要向那个主机发送信息,要想进行不同主机之间应用进程间的网络通信就必须要有端口号。比如你的手机相当于是一个客户端主机,手机里有聊天应用、短视频应用、游戏等各种应用,当你进入游戏时你的客户端会向游戏服务端发送请求,此时游戏服务端必须要有唯一的你的手机中该游戏应用的端口号,否则仅凭ip地址游戏服务端可能会将响应发送给你的手机的其他应用。
网络字节序
 
 
  
 
套接字(Socket)是一种独立于协议的网络编程接口。对网络中不同主机上的应用程序之间进行双向通信的端点的抽象,一个套接字就是网络中进程通信的一端,为应用层进程提供利用网络协议交换数据的机制。套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口、是应用程序与网络协议栈进行交互的接口。
创建套接字:

主机信息与套接口之间进行绑定:
对于服务端需要我们显式绑定,而对于客户端操作系统会自动绑定。

服务端/客户端向服务端/客户端发送消息:

服务端/客户端接收信息:

可以清空数据类型变量的函数bzero:

sockaddr_in结构体中的in_addr结构体类型源代码定义:

结构体sin_addr里包含了主机ip地址:

INADDR_ANY是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。
基于UDP 客户端多线程:
UdpClient.cxx
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
// 客户端基于多线程向服务端收发消息
#define SIZE 1024
void UsageMethod(const std::string &str)
{
    std::cout << str << "ser ip   ser port" << std::endl;
}
void *SendMessage(void *args)
{
    serverdata *svdata = static_cast<serverdata *>(args);
    std::string info; // 给服务端发信息所用的缓存区
    while (true)
    {
        std::cout << "Please Enter:";
        std::getline(std::cin, info);
        socklen_t len = sizeof(svdata->_server);
        sendto(svdata->_sockfd, info.c_str(), info.size(), 0, (const sockaddr *)&(svdata->_server), len);
    }
    return nullptr;
}
void *ReceiveMessage(void *args)
{
    serverdata *svdata = static_cast<serverdata *>(args);
    char inbuffer[SIZE] = {0};
    while (true)
    {
        struct sockaddr_in svtmp;
        socklen_t len = sizeof(svtmp);
        recvfrom(svdata->_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr *)&(svdata->_server), &len);
        std::cout << "client get message:" << inbuffer << std::endl;
    }
}
struct serverdata
{
    struct sockaddr_in _server;
    int _sockfd;
};
int main(int argc, char *argv[]) // 客户端不需要显式bind 端口号 和 ip地址
{
    if (argc != 3)
    {
        UsageMethod(argv[0]);
        exit(0);
    }
    std::string serverip = argv[1];
    std::string serverport = argv[2];
    // 服务端信息
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(serverip.c_str());
    auto port = std::stoi(serverport.c_str()); // 先将string类型的port转换为uint16_t类型以满足函数传参
    server.sin_port = htons(port);
    // 创建客户端的套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
    }
    serverdata sd;
    sd._sockfd = sockfd;
    sd._server = server;
    // 创建线程
    pthread_t sender, receiver;
    pthread_create(&sender, nullptr, SendMessage, &sd); // 先客户端发送信息的线程
    pthread_create(&receiver, nullptr, ReceiveMessage, &sd);
    //等待线程
    pthread_join(sender, nullptr);
    pthread_join(receiver, nullptr);
    close(sockfd);
    return 0;
}


















