用哪個程序做網(wǎng)站收錄好今日熱點新聞頭條排行榜
網(wǎng)絡(luò)編程基礎(chǔ)概念:
ip地址和端口號
ip地址是網(wǎng)絡(luò)協(xié)議地址(4字節(jié)32位,形式:xxx.xxx.xxx.xxx??? xxx在范圍[0, 255]內(nèi)),是IP協(xié)議提供的一種統(tǒng)一的地址格式,每臺主機的ip地址不同,一個主機可以有多個ip地址,一個ip地址只能被一個主機占用。
僅使用主機的ip地址就可以實現(xiàn)兩主機中不同的應(yīng)用進程進行網(wǎng)絡(luò)通信嗎?不可以。ip地址只是鎖定要向那個主機發(fā)送信息,要想進行不同主機之間應(yīng)用進程間的網(wǎng)絡(luò)通信就必須要有端口號。比如你的手機相當(dāng)于是一個客戶端主機,手機里有聊天應(yīng)用、短視頻應(yīng)用、游戲等各種應(yīng)用,當(dāng)你進入游戲時你的客戶端會向游戲服務(wù)端發(fā)送請求,此時游戲服務(wù)端必須要有唯一的你的手機中該游戲應(yīng)用的端口號,否則僅憑ip地址游戲服務(wù)端可能會將響應(yīng)發(fā)送給你的手機的其他應(yīng)用。
網(wǎng)絡(luò)字節(jié)序


套接字(Socket)是一種獨立于協(xié)議的網(wǎng)絡(luò)編程接口。對網(wǎng)絡(luò)中不同主機上的應(yīng)用程序之間進行雙向通信的端點的抽象,一個套接字就是網(wǎng)絡(luò)中進程通信的一端,為應(yīng)用層進程提供利用網(wǎng)絡(luò)協(xié)議交換數(shù)據(jù)的機制。套接字上聯(lián)應(yīng)用進程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過網(wǎng)絡(luò)協(xié)議進行通信的接口、是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議棧進行交互的接口。網(wǎng)絡(luò)字節(jié)序
創(chuàng)建套接字:
主機信息與套接口之間進行綁定:
?對于服務(wù)端需要我們顯式綁定,而對于客戶端操作系統(tǒng)會自動綁定。
服務(wù)端/客戶端向服務(wù)端/客戶端發(fā)送消息:
?服務(wù)端/客戶端接收信息:
?
可以清空數(shù)據(jù)類型變量的函數(shù)bzero:
sockaddr_in結(jié)構(gòu)體中的in_addr結(jié)構(gòu)體類型源代碼定義:
?結(jié)構(gòu)體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>// 客戶端基于多線程向服務(wù)端收發(fā)消息#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; // 給服務(wù)端發(fā)信息所用的緩存區(qū)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];// 服務(wù)端信息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轉(zhuǎn)換為uint16_t類型以滿足函數(shù)傳參server.sin_port = htons(port);// 創(chuàng)建客戶端的套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){perror("socket error");}serverdata sd;sd._sockfd = sockfd;sd._server = server;// 創(chuàng)建線程pthread_t sender, receiver;pthread_create(&sender, nullptr, SendMessage, &sd); // 先客戶端發(fā)送信息的線程pthread_create(&receiver, nullptr, ReceiveMessage, &sd);//等待線程pthread_join(sender, nullptr);pthread_join(receiver, nullptr);close(sockfd);return 0;
}