標籤:c_str host 網路 hello amp space cal 空間 現象
【多機測試】
若沒有多台電腦,可以使用虛擬機器
有多台電腦,串連交換器
觀察IP
ipconfig(Linux下是ifconfig)
檢測連通性
ping
【發送接收緩衝區】
SendTo()
a)存入資料和發送資料存在時間差
b)如果存入資料太快,太多,則發送緩衝區會滿
RecvFrom()
a)不論是否取,OS總是把資料收下存好
b)RecvFrom是從RecvBuf裡取走現成的資料,如果不及時取,則緩衝區滿。
緩衝區滿的處理
發送資料(兩種選擇)
(1)直到緩衝區有剩餘空間-阻塞
(2)新發送的資料沒有存入緩衝區
接受資料(兩種選擇)
(1)新資料不被接受
(2)刪除緩衝區已有資料,存放新的資料
丟包現象
設定發送/接受緩衝區的大小
if(1){int bufsize=128*1024;int ret=setsockopt(sock.hSock,SOL_SOCKET,SO_SNDBUF,//SO_RCVBUF(const char *)&bufsize,sizeof(int));}
【丟包】
一般情況下設定緩衝區大小並不能解決丟包問題
(1)發送是否均勻
(2)接受是否及時
(3)資料頻寬是否已經超過實際傳輸寬度
另外,即使HostA和HostB處理都沒問題,網路上任意一個中間節點裝置在轉寄該包時都有可能丟包。
結論:對UDP來說,丟包“家常便飯”,設計時考慮這一點
【網路位元組序】
網路上的資料是一個位元組一個位元組地串列傳輸的
"hello"
h->68
e->65
l->6C
l->6C
o->6F
unsigned int a=0x12345678
它在記憶體的排列
78 56 34 12
規定
規定低位元組在前,則稱為小端
規定高位元組在前,則稱為大端
大端與小端是一套(硬體和軟體),我們見到的主流都是小端
如intel/AMD,很少有大端系統
【網路傳輸時】
unsigned int a=0x12345678
如12 34 56 78(大端)
如78 56 34 12(小端)
慣例都是按大端傳輸
big-endian
一個int型資料佔4個位元組,下面按大端傳輸int型資料
【觀察】
//HostA#include<iostream>using namespace std;#include "afos/AfSocket.h"void Endian_intToChar(int temp,char bytes[]){bytes[0]=(char)(temp >> 24);bytes[1]=(char)(temp >> 16);bytes[2]=(char)(temp >> 8);bytes[3]=(char)(temp);}int main(){//發送方AfSockAddr local("192.168.1.105",9000);//發送方地址AfUdpSocket soc;soc.Open(local,true);cout<<"發送方-連接埠9000 ->"<<endl;while (1){cout<<"please push Enter!"<<endl;getchar();//每按一次斷行符號...AfSockAddr peer("192.168.1.105",9001);char bytes[4];int temp=0x34560012;//int型資料的傳輸不再深究Endian_intToChar(temp,bytes);soc.SendTo(bytes,4,peer);}soc.Close();return 0;}
//HostB#include<iostream>using namespace std;#include "afos/AfSocket.h"int Endian_CharToInt(char bytes[],int n)//四個位元組char轉為一個int型資料{int temp=0;temp+=(bytes[0]<<24);temp+=(bytes[1]<<16);temp+=(bytes[2]<<8);temp+=(bytes[3]);return temp;}int main(){//接受方AfSockAddr local("192.168.1.105",9001);//AfSockAddr local("192.168.1.104",9001);//接收方地址AfUdpSocket soc;soc.Open(local,true);cout<<"接收到-連接埠9001->"<<endl;char buffer[128];while (1){AfSockAddr peer;int len=soc.RecvFrom(buffer,128,peer);buffer[len]=‘\0‘;if (len>0){int temp;temp=Endian_CharToInt(buffer,len);printf("%08x\n",temp);}if (strcmp("quit",buffer)==0){break;}}soc.Close();return 0;}
【預設分配的連接埠號碼】
【連接埠的佔用】
【多個發送方,一個接收方】
【阻塞與逾時】
【1】預設分配的連接埠號碼
發送方可以不顯示指定連接埠號碼
AfUdpSocket soc;
soc.Open();
可以查看自動分配的連接埠號碼
AfSockAddr local;
sock.GetLocalAddr(local);
unsigned int port=local.GetPort();
printf("local port:%d\n",port);
注意:在發送資料的時候,才會自動分配連接埠。
【2】連接埠的佔用
當連接埠處於佔用時,再建立一個Socket,還使用相同的連接埠,則建立失敗,sock.Open()返回-1
一般設為可重用
sock.Open(local,true);//true允許重用,false不允許重用
【3】多個發送方,一個接收方
是誰發來的
string peer_ip=peer.GetIp_str();
int peer_port=peer.GetPort();
printf("from: IP->%s Port->%d",peer_ip.c_str(),peer_port);
【4】阻塞與逾時
sock.RecvFrom()緩衝區無資料則等待,即阻塞,可設定最大時間
設定接收逾時
sock.SetOpt_RecvTimeout(3000);//毫秒設定接收逾時
AfUdpSocket soc;
soc.SetOpt_RecvTimeout(3000);//毫秒設定接收逾時
int len=soc.RecvFrom(buffer,128,peer);
if (len<0)
{
printf("got %d\n",len);
}
非阻塞,定時查看(輪訓),有資料返回0,無資料返回-1
C++網路Socket