主頁 > 作業系統 > onps堆疊使用說明(1)——API介面手冊

onps堆疊使用說明(1)——API介面手冊

2022-11-10 06:16:49 作業系統

1. 底層API

       由協議堆疊底層提供的api,用于涉及底層操作的一些功能實作,這些api介面函式的原型定義分布于不同的檔案,它們被統一include進了onps.h中:

  • open_npstack_load:將協議堆疊載入目標系統,協議堆疊開始運行
  • open_npstack_unload:將協議堆疊載出目標系統,協議堆疊結束運行
  • route_add:添加一條靜態路由
  • route_del:洗掉一條靜態路由
  • route_del_ext:洗掉指定網卡在路由表中的所有路由條目,禁止網卡跨網段通訊
  • route_get_default:獲取預設路由
  • dhcp_req_addr:向dhcp服務器請求租用一個動態地址
  • ethernet_add:添加ethernet網卡
  • ethernet_del:洗掉ethernet網卡
  • ethernet_put_packet:將收到的ethernet報文推送給協議堆疊
  • netif_is_ready:網卡是否已就緒(進入作業狀態)
  • netif_get_by_name:通過網卡名稱查找網卡
  • buddy_alloc:申請一塊指定大小的記憶體
  • buddy_free:釋放申請的記憶體
  • buf_list_get_next_node:取出下一個鏈表節點
  • buf_list_get_len:鏈表所有節點攜帶的資料長度之和
  • buf_list_merge_packet:合并鏈表節點攜帶的資料將其放入用戶指定的緩沖區

open_npstack_load

功能

協議堆疊的入口函式,目標系統呼叫該函式啟動協議堆疊,換言之,在使用協議堆疊之前必須首先成功先呼叫該函式,

原型

BOOL open_npstack_load(EN_ONPSERR *penErr); 

入口引數

  • penErr:指向錯誤編碼的指標,當函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

加載成功,回傳TRUE;反之回傳FALSE,具體的錯誤資訊參見引數penErr回傳的錯誤碼,

示例

EN_ONPSERR enErr; 
if(open_npstack_load(&enErr)) //* 加載協議堆疊
{
    //* 協議堆疊加載成功,在這里添加你的自定義代碼
    ……
}
else
    printf("協議堆疊加載失敗, %s\r\n", onps_error(enErr)); //* 列印錯誤資訊

回傳目錄

open_npstack_unload

功能

協議堆疊的退出函式,一旦呼叫該函式,協議堆疊會結束運行并釋放占用的相關系統資源,

原型

void open_npstack_unload(void); 

入口引數

回傳值

示例

回傳目錄

route_add

功能

添加一條靜態路由到路由表,

原型

BOOL route_add(PST_NETIF pstNetif, UINT unDestination, UINT unGateway, UINT unGenmask, EN_ONPSERR *penErr); 

入口引數

  • pstNetif:指向網卡控制塊ST_NETIF的指標,該指標唯一的標識一塊網卡,其用于指定靜態路由添加到哪個網卡
  • unDestination:目標網段地址,如果其值為0則其為預設路由
  • unGateway:網關地址
  • unGenmask:子網掩碼
  • penErr:指向錯誤編碼的指標,當函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

添加成功則回傳TRUE,否則回傳FALSE,具體的錯誤資訊參見引數penErr回傳的錯誤碼,

示例

EN_ONPSERR enErr; 
PST_NETIF pstNetif = netif_get_by_name("eth0"); 
if(pstNetif && route_add(pstNetif, inet_addr_small("47.92.239.0"), inet_addr_small("192.168.0.1"), inet_addr_small("255.255.255.0"), &enErr))
{
    //* 添加成功,在這里添加你的自定義代碼
    ……
}
else
    printf("靜態路由添加失敗, %s\r\n", onps_error(enErr)); //* 列印錯誤資訊

回傳目錄

route_del

功能

洗掉一條靜態路由,

原型

void route_del(UINT unDestination); 

入口引數

  • unDestination:指定要洗掉的目標網段地址

回傳值

示例

回傳目錄

route_del_ext

功能

洗掉指定網卡在路由表中的所有路由條目,禁止網卡跨網段通訊,

原型

void route_del_ext(PST_NETIF pstNetif); 

入口引數

  • pstNetif:指向網卡控制塊ST_NETIF的指標,指定要洗掉哪個網卡的所有路由條目

回傳值

示例

回傳目錄

route_get_default

功能

獲取預設路由資訊,

原型

PST_NETIF route_get_default(void); 

入口引數

回傳值

回傳預設路由系結的網卡控制塊首地址,

示例

回傳目錄

dhcp_req_addr

功能

啟動dhcp客戶端,向dhcp服務器請求租用一個動態地址,

原型

BOOL dhcp_req_addr(PST_NETIF pstNetif, EN_ONPSERR *penErr); 

入口引數

  • pstNetif:指定要進行dhcp請求的網卡
  • penErr:指向錯誤編碼的指標,當函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

請求成功則回傳TRUE,否則回傳FALSE,具體的錯誤資訊參見引數penErr回傳的錯誤碼,

示例

參見上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

ethernet_add

功能

增加新的ethernet網卡到協議堆疊,

原型

PST_NETIF ethernet_add(const CHAR *pszIfName,

                       const UCHAR ubaMacAddr[ETH_MAC_ADDR_LEN],

                       PST_IPV4 pstIPv4,

                       PFUN_EMAC_SEND pfunEmacSend,

                       void (*pfunStartTHEmacRecv)(void *pvParam),

                       PST_NETIF *ppstNetif,

                       EN_ONPSERR *penErr); 

入口引數

  • pszIfName:網卡名稱
  • ubaMacAddr:網卡 mac 地址
  • pstIPv4:指向 ST_IPV4 結構體的指標(include/netif/netif.h),這個結構體保存用戶指定的 ip地址、網關、dns、子網掩碼等配置資訊
  • pfunEmacSend:函式指標,指向發送函式,函式原型為 INT(* PFUN_EMAC_SEND)(SHORT sBufListHead, UCHAR *pubErr),這個指標指向的其實就是網卡發送函式
  • pfunStartTHEmacRecv:指向執行緒啟動函式的指標,協議堆疊使用該指標指向的函式啟動協議堆疊內部作業執行緒——ethernet網卡接收執行緒
  • ppstNetif:二維指標,協議堆疊成功注冊網卡后 ethernet_add()函式會回傳一個 PST_NETIF 指標給呼叫者,這個引數指向這個指標,其最侄訓被協議堆疊通過 pvParam 引數傳遞給 pfunStartTHEmacRecv 指向的函式
  • penErr:指向錯誤編碼的指標,當函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

注冊成功,回傳一個 PST_NETIF 型別的指標,該指標指向新添加的網卡控制塊,唯一的標識新添加的這塊網卡;注冊失敗則回傳 NULL,具體錯誤資訊參見 penErr引數攜帶的錯誤碼,

示例

參見上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

ethernet_del

功能

洗掉ethernet網卡,

原型

void ethernet_del(PST_NETIF *ppstNetif); 

入口引數

  • ppstNetif:指向網卡控制塊PST_NETIF指標的指標,其指向ethernet_add()函式回傳的PST_NETIF指標的首地址

回傳值

示例

回傳目錄

ethernet_put_packet

功能

將收到的ethernet報文推送給協議堆疊,

原型

void ethernet_put_packet(PST_NETIF pstNetif, PST_SLINKEDLIST_NODE pstNode); 

入口引數

  • pstNetif:指向網卡控制塊ST_NETIF的指標
  • pstNode:指向協議堆疊ethernet網卡接收鏈表節點的指標

回傳值

示例

參見上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

netif_is_ready

功能

檢查網卡是否已進入或正處于正常作業狀態,

原型

BOOL netif_is_ready(const CHAR *pszIfName); 

入口引數

  • pszIfName:指向網卡名稱的指標

回傳值

回傳TRUE,網卡已就緒;反之則回傳FALSE,

示例

回傳目錄

netif_get_by_name

功能

通過網卡名稱查找網卡,

原型

PST_NETIF netif_get_by_name(const CHAR *pszIfName); 

入口引數

  • pszIfName:指向網卡名稱的指標

回傳值

存在則回傳指向網卡控制塊ST_NETIF的指標;否則回傳NULL,

示例

回傳目錄

buddy_alloc

功能

向記憶體管理單元(mmu)申請一塊指定大小的記憶體,

原型

void *buddy_alloc(UINT unSize, EN_ONPSERR *penErr); 

入口引數

  • unSize:申請分配的記憶體大小,單位:位元組
  • penErr:指向錯誤編碼的指標,當函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

申請成功回傳記憶體首地址;反之則回傳NULL,具體錯誤資訊參見 penErr引數攜帶的錯誤碼,

示例

參見buf_list_merge_packet函式示例或上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

buddy_free

功能

歸還(釋放)先前通過buddy_alloc()函式申請的記憶體,

原型

BOOL buddy_free(void *pvStart); 

入口引數

  • pvStart:指向要歸還的記憶體首地址的指標

回傳值

成功歸還記憶體回傳TRUE;當pvStart指向的并不是buddy_alloc()函式回傳的記憶體首地址時則回傳FALSE,

示例

參見buf_list_merge_packet函式示例,

回傳目錄

buf_list_get_next_node

功能

按鏈接順序從鏈表首部逐個取出鏈表節點,

原型

void *buf_list_get_next_node(SHORT *psNextNode, USHORT *pusDataLen); 

入口引數

  • psNextNode:指向鏈表下一個節點的指標
  • pusDataLen:指向資料長度的指標,出口引數,其用于接收節點攜帶的資料長度

回傳值

如果尚未到達鏈表尾部,則回傳當前鏈表節點攜帶的資料的首地址;反之則回傳NULL,

示例

參見上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

buf_list_get_len

功能

統計鏈表所有節點攜帶的資料長度之和,

原型

UINT buf_list_get_len(SHORT sBufListHead); 

入口引數

  • sBufListHead:鏈表首地址

回傳值

回傳鏈表所有節點攜帶的資料長度之和,

示例

參見buf_list_merge_packet函式示例或上一篇博文《onps堆疊移植說明(3)——添加網卡》,

回傳目錄

buf_list_merge_packet

功能

從鏈表首節點開始順序取出資料將其放入用戶指定的緩沖區,把零散的鏈表資料合并成一塊連續資料,

原型

void buf_list_merge_packet(SHORT sBufListHead, UCHAR *pubPacket); 

入口引數

  • sBufListHead:鏈表首地址
  • pubPacket:指向用戶緩沖區的指標,其用于接收合并后的資料以回傳給用戶使用

回傳值

示例

EN_ONPSERR enErr; 
UINT unDataLen = buf_list_get_len(sBufListHead /* 鏈表首地址 */); 
UCHAR *pubBuf = (UCHAR *)buddy_alloc(unDataLen, &enErr); //* 申請一塊緩沖區用于保存合并后的資料
if(pubBuf)
{
    //* 合并,合并后的資料保存在了pubBuf中,資料長度為unDataLen
    buf_list_merge_packet(sBufListHead, pubBuf); 
    
    //* 在這里增加你自己的代碼處理合并合并后的資料
    ……
    
    //* 處理完畢,釋放剛才申請的記憶體
    buddy_free(pubBuf); 
}

回傳目錄

2. Berkeley sockets

       協議堆疊提供的伯克利套接字(Berkeley sockets)并不是嚴格按照傳統socket標準設計實作的,而是我根據以往socket編程經驗,以方便用戶使用、簡化用戶編碼為設計目標,重新宣告并定義的一組常見socket介面函式,協議堆疊簡化了傳統BSD socket編程需要的一些繁瑣操作,將一些不必要的操作細節改為底層實作,比如select/poll模型、阻塞及非阻塞讀寫操作等,簡化并不意味著推翻,socket介面函式的基本定義、主要引數、使用方法并沒有改變,你完全可以根據以往經驗快速上手并熟練使用onps堆疊sockets,這一點相信你已經從前面的測驗代碼中得到了佐證,
       socket層所有介面函式的實作原始碼被封裝在了單獨的一個檔案中,參見bsd/socket.c,其對應的頭檔案socket.h有這些介面函式的定義和說明,目前協議堆疊提供的socket介面函式有十幾個,能夠滿足絕大部分應用場景的需求,這些介面函式如下:

  • socket:創建一個socket,目前僅支持udp和tcp兩種型別
  • close:關閉一個socket,釋放當前占用的協議堆疊資源
  • connect:與目標tcp服務器建立連接(阻塞型)或系結一個固定的udp服務器地址
  • connect_nb:與目標tcp服務器建立連接(非阻塞型)
  • is_tcp_connected:獲取當前tcp鏈路的連接狀態
  • send:資料發送函式,tcp鏈路下為阻塞型
  • send_nb:資料發送函式,非阻塞型
  • is_tcp_send_ok:資料是否已成功送達tcp鏈路的對端(收到tcp ack報文)
  • sendto:udp資料發送函式,發送資料到指定目標地址
  • recv:資料接收函式,udp/tcp鏈路通用
  • recvfrom:資料接收函式,用于udp鏈路,接收資料的同時函式會回傳資料源的地址資訊
  • socket_set_rcv_timeout:設定recv()函式接收等待的時長,單位:秒
  • bind:系結一個固定埠、地址
  • listen:tcp服務器進入監聽狀態
  • accept:接受一個到達的tcp連接請求
  • tcpsrv_recv_poll:tcp服務器專用函式,等待任意一個或多個tcp客戶端資料到達信號
  • socket_get_last_error:獲取socket最近一次發生的錯誤資訊
  • socket_get_last_error_code:獲取socket最近一次發生的錯誤編碼

socket

功能

創建一個socket,支持udp和tcp兩種型別,即:SOCK_DGRAM和SOCK_STREAM,注意,不使用時一定要呼叫close()函式關閉,以釋放其占用的協議堆疊相關資源,

原型

SOCKET socket(INT family, INT type, INT protocol, EN_ONPSERR *penErr); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • type:指定socket型別,支持SOCK_STREAM和SOCK_DGRAM兩種型別,前者為tcp,后者為udp
  • protocol:未使用,固定為0
  • penErr:指向錯誤編碼的指標,當socket()函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

執行成功回傳socket句柄,失敗回傳INVALID_SOCKET,具體的錯誤資訊參見penErr引數回傳的錯誤碼,

示例

EN_ONPSERR enErr;
//* tcp
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET == hSocket) //* 回傳一個無效的socket 
  printf("%s\r\n", onps_error(enErr)); //*列印錯誤資訊

//* udp
SOCKET hSocket = socket(AF_INET, SOCK_DGRAM, 0, &enErr);
……

回傳目錄

close

功能

關閉socket,釋放占用的協議堆疊資源,

原型

void close(SOCKET socket);

入口引數

  • socket:要關閉的socket句柄

回傳值

示例

EN_ONPSERR enErr;
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, 0, &enErr);
……
if(INVALID_SOCKET != hSocket)
    close(hSocket);

回傳目錄

connect

功能

用于tcp型別的socket時,其功能為與目標服務器建立tcp連接,阻塞型;用于udp型別的socket時,其功能為系結一個固定的目標通訊地址,udp通訊均與這個固定地址進行,

原型

INT connect(SOCKET socket, const CHAR *srv_ip, USHORT srv_port, INT nConnTimeout);

入口引數

  • socket:要進行connect操作的socket句柄
  • srv_ip:目標服務器地址
  • srv_port:目標服務器埠
  • nConnTimeout:僅用于tcp通訊,指定連接超時時間(單位:秒),引數值如小于等于0則協議堆疊會采用預設值,該值由TCP_CONN_TIMEOUT宏指定(參見sys_config.h);udp通訊未使用這個引數,可以指定任意一個值

回傳值

 0:連接成功

-1:連接失敗,具體的錯誤資訊通過onps_get_last_error()獲得

示例

EN_ONPSERR enErr;
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET == hSocket)
{
    printf("%s\r\n", onps_error(enErr)); 
    return; 
}

if(!connect(hSocket, "47.92.239.107", 6410, 10)) 
{
    //* 連接成功,在這里添加你的自定義代碼
    …… 
}
else
{
    //* 連接失敗,列印錯誤資訊
    printf("%s\r\n", onps_get_last_error(hSocket, NULL));
}
……
close(hSocket);

回傳目錄

connect_nb

功能

僅用于tcp型別的socket,非阻塞型,與目標tcp服務器建立連接,

原型

INT connect_nb(SOCKET socket, const CHAR *srv_ip, USHORT srv_port);

入口引數

  • socket:要進行connect操作的socket句柄
  • srv_ip:目標服務器地址
  • srv_port:目標服務器埠

回傳值

 0:連接成功
 1:連接中
-1:連接失敗,具體的錯誤資訊通過onps_get_last_error()獲得

示例

EN_ONPSERR enErr;
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET == hSocket)
{
    printf("%s\r\n", onps_error(enErr)); 
    return; 
}

//* 回圈等待tcp連接成功
while(1)
{
    INT nRtnVal = connect_nb(hSocket, "47.92.239.107", 6410);
    if(!nRtnVal)
    {
        //* 連接成功,在這里增加你的自定義代碼
        ……
        break; //* 退出回圈,不再輪詢檢查tcp連接行程
    }
    else if(nRtnVal < 0)
    {  
        //* 連接失敗,列印錯誤資訊并退出回圈不再輪詢檢查tcp連接行程
        printf("%s\r\n", onps_get_last_error(hSocket, NULL));
        break;  
    }
    else; 
    
    //* 連接中,tcp三次握手操作尚未完成,此時你可以干點別的事情,或者延時一小段時間后繼續檢查當前連接狀態
    ……
    os_sleep_secs(1);
}
……
close(hSocket);

回傳目錄

is_tcp_connected

功能

檢查tcp鏈路是否處于連接狀態,

原型

INT is_tcp_connected(SOCKET socket, EN_ONPSERR *penErr);

入口引數

  • socket:socket句柄
  • penErr:指向錯誤編碼的指標,函式執行失敗時該引數用于接收實際的錯誤碼

回傳值

 0:未連接
 1:已連接
-1:函式執行失敗,具體的錯誤資訊通過引數penErr獲得

示例

EN_ONPSERR enErr;
……
INT nRtnVal = is_tcp_connected(hSocket, &enErr); 
if(nRtnVal > 0)
    printf("已連接\r\n");
else if(!nRtnVal)
    printf("未連接\r\n");
else
    printf("檢查失敗,%s\r\n", onps_error(enErr)); 
……

回傳目錄

send

功能

發送資料到目標地址,注意tcp鏈路下為阻塞型,直至收到對端的tcp層ack報文或超時才會回傳,udp鏈路下為非阻塞型,且只有在呼叫connect()函式后才能使用這個函式,

原型

INT send(SOCKET socket, UCHAR *pubData, INT nDataLen, INT nWaitAckTimeout);

入口引數

  • socket:socket句柄
  • pubData:指向要發送的資料的指標
  • nDataLen:要發送的資料的長度,單位:位元組
  • nWaitAckTimeout:僅用于tcp鏈路,指定發送超時時間,單位:秒,如引數值不大于0,則協議堆疊采用系統預設值,該值由TCP_ACK_TIMEOUT宏指定(參見sys_config.h);udp鏈路未使用,可指定任意值

回傳值

發送成功,則回傳值等于nDataLen;發送失敗,回傳值不等于nDataLen,具體的錯誤資訊通過onps_get_last_error()獲得,

示例

/* tcp鏈路下send()函式使用示例 */
EN_ONPSERR enErr;
……
UCHAR ubUserData[128]; 
INT nSndBytes, nSndNum = 0; 

__lblSend:
if(nSndNum > 2)  
{
    //* 超出重傳次數,不再重傳,可以關閉當前tcp鏈路重連tcp服務器或者你自己的其它處理方式
    ……
    return;
}
nSndBytes = send(hSocket, ubUserData, sizeof(ubUserData), 3); 
if(sizeof(ubUserData) == nSndBytes)
{
    //* 發送成功,在這里添加你自己的處理代碼
    ……
}
else
{
    const CHAR *pszErr = onps_get_last_error(hSocket, &enErr); 
    if(enErr == ERRTCPACKTIMEOUT) //* 等待tcp層的ack報文超時
    {
        //* 資料重傳,用戶層實作tcp層重傳機制
        nSndNum++;
        goto __lblSend;
    }
    else //* 其它錯誤,意味著底層協議堆疊捕捉到了記憶體不夠用、網卡故障等類似的嚴重問題 
    {
        //* 沒必要觸發重傳機制了,根據你自己的具體情形增加容錯處理代碼并列印錯誤資訊 
        …… 
        printf("發送失敗,%s\r\n", pszErr);
    }
}
……

回傳目錄

send_nb

功能

發送資料到目標地址,非阻塞型,其它與send函式完全相同,

原型

INT send_nb(SOCKET socket, UCHAR *pubData, INT nDataLen);

入口引數

  • socket:socket句柄
  • pubData:指向要發送的資料的指標
  • nDataLen:要發送的資料的長度,單位:位元組

回傳值

發送成功,則回傳值等于nDataLen;回傳值為0,上一組數正處于發送中(尚未收到對端的tcp ack報文),需要等待其發送成功后再發送當前資料;發送失敗,回傳值小于等于0,具體的錯誤資訊通過onps_get_last_error()獲得,

示例

/* tcp鏈路下send_nb()函式使用示例 */
EN_ONPSERR enErr;
……
UCHAR ubUserData[128]; 
INT nRtnVal;

__lblSend:
nRtnVal = send_nb(hSocket, ubUserData, sizeof(ubUserData));
if(sizeof(ubUserData) == nRtnVal)
{
    //* 呼叫is_tcp_send_ok()函式等待是否已成功送達對端,或者(同時)做點別的事情
    ……
}
else if(0 == nRtnVal)
{
    //* 上一組資料尚未發送完畢,需要等待發送完畢后再發送當前資料,等待期間你可以在這里做點別的事情
    ……
    goto __lblSend; 
}
else
{
    //* 發送失敗,協議堆疊底層捕捉到了一個嚴重的系統錯誤,這里增加你的容錯代碼并列印錯誤資訊,不再繼續發送
    ……
    printf("發送失敗,%s\r\n", onps_get_last_error(hSocket, NULL));
}
……

回傳目錄

is_tcp_send_ok

功能

非阻塞型,資料是否已成功送達tcp鏈路的對端(已收到對端回饋的tcp ack報文),

原型

INT is_tcp_send_ok(SOCKET socket);

入口引數

  • socket:socket句柄

回傳值

 0:發送中
 1:發送成功
-1:發送失敗,具體錯誤資訊通過onps_get_last_error()函式獲得

示例

EN_ONPSERR enErr;
……
UCHAR ubUserData[128]; 
INT nRtnVal;

__lblSend:
nRtnVal = send_nb(hSocket, ubUserData, sizeof(ubUserData));
if(sizeof(ubUserData) == nRtnVal)
{
    //* 資料已通過網卡成功送出,接下來輪詢等待對端回饋的tcp ack報文,確保資料成功送達對端
    while(1)
    {
        INT nResult = is_tcp_send_ok(hSocket); 
        if(nResult == 1)
        {
            //* 發送成功了,退出輪詢等待  
            break;
        }
        else if(nResult < 0)
        {
            //* 協議堆疊底層捕捉到了一個嚴重的系統錯誤,不再輪詢等待,并列印錯誤資訊
            ……
            printf("%s\r\n", onps_get_last_error(hSocket, NULL));
            break; 
        }
        
        //* 發送中,在這里你可以做點別的事情
        ……
    }
  
    ……
}
else if(0 == nRtnVal)
{
    //* 上一組資料尚未發送完畢,需要等待發送完畢后再發送當前資料,等待期間你可以在這里做點別的事情
    ……
    goto __lblSend; 
}
else
{
    //* 發送失敗,協議堆疊底層捕捉到了一個嚴重的系統錯誤,這里列印錯誤資訊,不再繼續發送
    printf("發送失敗,%s\r\n", onps_get_last_error(hSocket, NULL));
}
……

回傳目錄

sendto

功能

非阻塞型,僅用于udp通訊,發送資料到指定的目標地址,

原型

INT sendto(SOCKET socket, const CHAR *dest_ip, USHORT dest_port, UCHAR *pubData, INT nDataLen);

入口引數

  • socket:socket句柄
  • dest_ip:目標地址
  • dest_port:目標埠
  • pubData:指向要發送的資料的指標
  • nDataLen:要發送的資料的長度,單位:位元組

回傳值

發送成功,回傳值等于nDataLen,反之則發送失敗,具體的錯誤資訊通過onps_get_last_error()獲得,

示例

EN_ONPSERR enErr;
……
UCHAR ubUserData[128]; 
INT nSndBytes = sendto(hSocket, "47.92.239.107", 6411, ubUserData, sizeof(ubUserData)); 
if(sizeof(ubUserData) == nSndBytes)
{
    //* 發送成功,在這里增加你自己的業務代碼
    ……
}
else
{
    //* 發送失敗,在這里增加你自己的容錯代碼并列印錯誤資訊
    ……
    printf("發送失敗,%s\r\n", onps_get_last_error(hSocket, NULL));
}
……

回傳目錄

recv

功能

讀取鏈路對端發送的資料,其阻塞型別取決于socket_set_rcv_timeout()函式設定的接收等待時長,預設為阻塞型,一直等待直至收到資料或報錯,

原型

INT recv(SOCKET socket, UCHAR *pubDataBuf, INT nDataBufSize);

入口引數

  • socket:socket句柄
  • pubDataBuf:指向資料接識訓沖區的指標
  • nDataBufSize:資料接識訓沖區的大小,單位:位元組

回傳值

大于等于0為實際到達的資料長度,單位:位元組;小于0,接收失敗,具體的的錯誤資訊通過onps_get_last_error()獲得,

示例

EN_ONPSERR enErr;
……
UCHAR ubRcvBuf[1500]; 
INT nRcvBytes = recv(hSocket, ubRcvBuf, sizeof(ubRcvBuf));
if(nRcvBytes > 0) //* 收到資料
{
    ……
}
else
{
    if(nRcvBytes < 0) //* 協議堆疊底層捕捉到了一個嚴重錯誤,在這里增加你的容錯代碼并列印錯誤資訊
    {
        ……
        printf("%s\r\n", onps_get_last_error(hSocket, NULL));
    }
}
……

回傳目錄

socket_set_rcv_timeout

功能

設定recv()函式接收等待的時長,其設定的接收等待時長決定了recv()函式的阻塞型別,
等于0:非阻塞,recv()不等待立即回傳
大于0:阻塞,recv()等待指定時長直至資料到達或超時
小于0:阻塞,recv()一直等待直至資料到達或出錯

原型

BOOL socket_set_rcv_timeout(SOCKET socket, CHAR bRcvTimeout, EN_ONPSERR *penErr); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • bRcvTimeout:recv()函式的接收等待時長,單位:秒
  • penErr:指向錯誤編碼的指標,當socket()函式執行失敗,該引數用于接收實際的錯誤碼

回傳值

設定成功回傳TRUE,否則回傳FALSE,具體的錯誤資訊通過引數penErr獲得,

示例

EN_ONPSERR enErr;
……
if(!socket_set_rcv_timeout(hSocket, 1, &enErr))
{
    //* 設定失敗,列印錯誤資訊,此時系統采用預設值,即recv()函式一直等待直至收到資料或協議堆疊報錯
    printf("%s\r\n", onps_error(enErr)); 
}
……

回傳目錄

recvfrom

功能

接收資料并回傳資料源的地址資訊,僅用于udp通訊,

原型

INT recvfrom(SOCKET socket, UCHAR *pubDataBuf, INT nDataBufSize, in_addr_t *punFromIP, USHORT *pusFromPort); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • pubDataBuf:指向資料接識訓沖區的指標
  • nDataBufSize:資料接識訓沖區的大小,單位:位元組
  • punFromIP:指向資料源ip地址的指標
  • pusFromPort:指向資料源埠的指標

回傳值

實際收到的資料的長度,單位:位元組;小于0則接收失敗,具體的的錯誤資訊通過onps_get_last_error()獲得,

示例

EN_ONPSERR enErr;
……
UCHAR ubRcvBuf[512]; 
in_addr_t unFromIp; 
USHORT usFromPort; 
INT nRcvBytes = recvfrom(hSocket, ubRcvBuf, sizeof(ubRcvBuf), &unFromIp, &usFromPort);
if(nRcvBytes > 0) //* 收到資料
{
    CHAR szAddr[20]; 
    printf("收到來自地址%s:%d的%d位元組的資料\r\n", inet_ntoa_safe_ext(unFromIp, szAddr), usFromPort, nRcvBytes);
    ……  
}
else
{
    if(nRcvBytes < 0) //* 協議堆疊底層捕捉到了一個嚴重錯誤,在這里增加你的容錯代碼并列印錯誤資訊
    {
        ……
        printf("發送失敗,%s\r\n", onps_get_last_error(hSocket, NULL));
    }
}
……

回傳目錄

bind

功能

系結一個ip地址和埠,

原型

INT bind(SOCKET socket, const CHAR *pszNetifIp, USHORT usPort); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • pszNetifIp:指向要系結的ip地址的指標,為NULL系結任意網路介面
  • usPort: 要系結的埠

回傳值

 0:成功
-1:失敗,具體的的錯誤資訊通過onps_get_last_error()獲得

示例

EN_ONPSERR enErr;
……
SOCKET hSockSrv = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET != hSockSrv)
{
    if(!bind(hSockSrv, NULL, 6411)) //* 系結成功
        ……
    else //* 系結失敗
        printf("%s\r\n", onps_get_last_error(hSocket, NULL)); //* 列印錯誤資訊
}
else
    printf("%s\r\n", onps_error(enErr)); //*列印錯誤資訊
……

回傳目錄

listen

功能

tcp服務器進入監聽狀態,等待tcp客戶端連接請求的到達,

原型

INT listen(SOCKET socket, USHORT backlog); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • backlog:等待用戶層接受(accept)連接請求的tcp客戶端數量

回傳值

 0:成功
-1:失敗,具體的的錯誤資訊通過onps_get_last_error()獲得

示例

EN_ONPSERR enErr;
……
SOCKET hSockSrv = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET != hSockSrv)
{
  if(!bind(hSockSrv, NULL, 6411)) //* 系結成功
  {
      if(!listen(hSockSrv, usBacklog)) //* 進入監聽狀態
      {
          ……
      }
      else //* 失敗
          printf("%s\r\n", onps_get_last_error(hSocket, NULL)); //* 列印錯誤資訊
}
else //* 系結失敗
    printf("%s\r\n", onps_get_last_error(hSocket, NULL)); //* 列印錯誤資訊
}
else
    printf("%s\r\n", onps_error(enErr)); //*列印錯誤資訊
……

回傳目錄

accept

功能

阻塞/非阻塞型,接受一個到達的tcp連接請求,

原型

SOCKET accept(SOCKET socket, in_addr_t *punCltIP, USHORT *pusCltPort, INT nWaitSecs, EN_ONPSERR *penErr); 

入口引數

  • family:目前僅支持IPv4地址,即AF_INET,其它地址族如AF_INET6之類的不支持
  • punCltIP:指向tcp客戶端Ip地址的指標
  • pusCltPort:指向tcp客戶端埠的指標
  • nWaitSecs:指定等待時長,單位:秒,0,不等待,立即回傳;大于0,等待指定時間直至收到一個客戶端連接請求或超時;小于0,一直等待,直至收到一個客戶端連接請求或協議堆疊報錯
  • penErr:指向錯誤編碼的指標,函式執行失敗時該引數用于接收實際的錯誤碼

回傳值

回傳請求連接的tcp客戶端的socket句柄;當沒有新的客戶端連接請求到達或協議堆疊報錯時回傳INVALID_SOCKET,具體的錯誤碼通過penErr引數獲得,

示例

EN_ONPSERR enErr;
……
SOCKET hSockSrv = socket(AF_INET, SOCK_STREAM, 0, &enErr);
if(INVALID_SOCKET != hSockSrv)
{
    if(!bind(hSockSrv, NULL, 6411)) //* 系結成功
    {
        if(!listen(hSockSrv, usBacklog)) //* 進入監聽狀態
        {
            //* 回圈等待并處理到達的tcp連接請求
            while(1)
            {
                in_addr_t unCltIP; 
                USHORT usCltPort;
                SOCKET hSockClt = accept(hSockSrv, &unCltIP, &usCltPort, 1, &enErr); 
                if(INVALID_SOCKET != hSockClt) //* 回傳了一個有效的客戶端socket句柄
                {
                    //* 新的客戶端到達,在這里增加你的自定義代碼
                    …… 
                }
                else
                {
                    //* 錯誤碼為ERRNO代表無錯誤發生,意味著沒有新的客戶端連接請求到達,回到回圈開始處繼續等待即可
                    if(ERRNO == enErr)
                        continue; 
                    else //* 不等于ERRNO意味著協議堆疊報錯,需要處理
                    {
                        ……
                        printf("%s\r\n", onps_error(enErr)); //* 列印錯誤資訊
                    }
                }
            }
        }
        else //* 失敗
            printf("%s\r\n", onps_get_last_error(hSocket, NULL)); //* 列印錯誤資訊
    }
    else //* 系結失敗
        printf("%s\r\n", onps_get_last_error(hSocket, NULL)); //* 列印錯誤資訊
}
else
    printf("%s\r\n", onps_error(enErr)); //*列印錯誤資訊
……

回傳目錄

tcpsrv_recv_poll

功能

阻塞/非阻塞型,tcp服務器資料接收專用函式,等待任意一個或多個tcp客戶端資料到達信號,協議堆疊利用rtos提供的信號量實作了一個poll模型,當有一個及以上的tcp客戶端資料到達,均會觸發一個信號到用戶層,我們通過tcpsrv_recv_poll()函式等待這個信號,這個函式的第二個引數值表示這個函式最長等待多少秒,等待期間有任意一個或多個客戶端資料到達則立即回傳最先到達的這個客戶端的socket,繼續呼叫這個函式則繼續回傳下一個客戶端socket,直至回傳一個無效的socket才意味著當前所有已送達的資料均已讀取完畢,已經沒有任何客戶端有新資料到達了,

原型

SOCKET tcpsrv_recv_poll(SOCKET hSocketSrv, INT nWaitSecs, EN_ONPSERR *penErr); 

入口引數

  • hSocketSrv:tcp服務器的socket句柄
  • nWaitSecs:等待時長,單位:秒,0,不等待,立即回傳;大于0,等待指定時間直至收到一個/多個客戶端資料到達信號或超時;小于0,一直等待,直至收到一個/多個客戶端資料到達信號或協議堆疊報錯
  • penErr:指向錯誤編碼的指標,函式執行失敗時該引數用于接收實際的錯誤碼

回傳值

回傳已經收到資料的tcp客戶端的socket句柄;當沒有任何tcp客戶端收到資料或協議堆疊報錯時回傳INVALID_SOCKET,具體的錯誤碼通過penErr引數獲得,

示例

//* 完成tcp服務器的資料讀取作業
void tcp_server_recv(void *pvData)
{
    SOCKET hSockClt; 
    EN_ONPSERR enErr; 
    INT nRcvBytes; 
    UCHAR ubaRcvBuf[100]; 
    
    while(TRUE)
    {
        hSockClt = tcpsrv_recv_poll(l_hSockSrv, 1, &enErr); 
        if(INVALID_SOCKET != hSockClt) //* 有效的socket
        {
            //* 注意這里一定要盡量讀取完畢該客戶端的所有已到達的資料,因為每個客戶端只有新資料到達時才會觸發一個信號到用戶層
            //* ,如果你沒有讀取完畢就只能等到該客戶端送達下一組資料時再讀取了,這可能會導致資料處理延遲問題
            while(TRUE)
            {
                //* 讀取資料
                nRcvBytes = recv(hSockClt, ubaRcvBuf, 256);
                if(nRcvBytes > 0)
                {
                    //* 原封不動的回送給客戶端,利用回顯來模擬服務器回饋應答報文的場景
                    send(hSockClt, ubaRcvBuf, nRcvBytes, 1);       
                }
                else //* 已經讀取完畢
                {
                    if(nRcvBytes < 0)
                    {
                        //* 協議堆疊底層報錯,這里需要增加你的容錯代碼處理這個錯誤并列印錯誤資訊
                        printf("%s\r\n", onps_get_last_error(hSocket, NULL));
                    }
                    break; 
                }
            }  
        }
        else //* 無效的socket
        {
            //* 回傳一個無效的socket時需要判斷是否存在錯誤,如果不存在則意味著1秒內沒有任何資料到達,否則列印這個錯誤
            if(ERRNO != enErr)
                printf("tcpsrv_recv_poll() failed, %s\r\n", onps_error(enErr)); 
        }
    }
}

回傳目錄

socket_get_last_error/onps_get_last_error

功能

獲取socket最近一次發生的錯誤,包括描述資訊及錯誤編碼,該函式其實是前面示例代碼中出現的onps_get_last_error()函式的二次封裝,功能及使用方式與之完全相同,

原型

const CHAR *socket_get_last_error(SOCKET socket, EN_ONPSERR *penErr); 

入口引數

  • socket:socket句柄
  • penErr:指向錯誤編碼的指標,該引數用于接收實際的錯誤碼

回傳值

回傳值為字串指標,指向socket最近一次發生的錯誤描述字串,

示例

略,

回傳目錄

socket_get_last_error_code

功能

獲取socket最近一次發生的錯誤編碼,

原型

EN_ONPSERR socket_get_last_error_code(SOCKET socket); 

入口引數

  • socket:socket句柄

回傳值

回傳值為socket最近一次發生的錯誤編碼,

示例

略,

回傳目錄

3. 常用工具函式

       協議堆疊還提供了一組網路編程常見的工具函式以供用戶使用,同時還提供了一些常用的比如字串操作、16進制格式化轉換輸出等函式:

  • htonxx系列:網路位元組序轉換函式
  • inet_xx系列:網路地址轉換函式
  • ip_addressing:檢查ip地址是否在同一網段
  • strtok_safe:執行緒安全的strtok函式
  • snprintf_hex:將16進制資料格式化轉換成字串
  • printf_hex:將16進制資料格式化轉換成字串后輸出到控制臺
  • onps_error:將協議堆疊回傳的錯誤碼轉換成具體的描述字串

htonll

功能

實作64位長整型數的網路位元組序轉換,

原型

LONGLONG htonll(LONGLONG llVal); 

入口引數

  • llVal:64位長整型數

回傳值

回傳值為位元組序轉換后的64位長整型數,

示例

略,

回傳目錄

htonl

功能

實作32位整型數的網路位元組序轉換,

原型

LONG htonl(LONG lVal); 

入口引數

  • lVal:32整型數

回傳值

回傳值為位元組序轉換后的32位整型數,

示例

略,

回傳目錄

htons

功能

實作16位短整型數的網路位元組序轉換,

原型

SHORT htonl(SHORT sVal); 

入口引數

  • sVal:16位短整型數

回傳值

回傳值為位元組序轉換后的16位短整型數,

示例

略,

回傳目錄

inet_addr

功能

實作點分十進制1Pv4地址到4字節無符號整型地址的轉換,即10.0.1.2轉換為0x0A000102,

原型

in_addr_t inet_addr(const char *pszIP); 

入口引數

  • pszIP:指向點分十進制IPv4地址字串的指標

回傳值

回傳值為無符號32位整型地址,

示例

略,

回傳目錄

inet_addr_small

功能

實作點分十進制1Pv4地址到4位元組無符號整型地址的轉換,即10.0.1.2轉換為0x0201000A,

原型

in_addr_t inet_addr_small(const char *pszIP); 

入口引數

  • pszIP:指向點分十進制IPv4地址字串的指標

回傳值

回傳值為無符號32位整型地址,

示例

略,

回傳目錄

inet_ntoa

功能

注意,這是一個執行緒不安全的函式,實作in_addr型別的地址到點分十進制1Pv4地址的轉換,

原型

char *inet_ntoa(struct in_addr stInAddr); 

入口引數

  • stInAddr:指向in_addr型別的IPv4地址的指標

回傳值

回傳字串指標,指向轉換后的點分十進制格式的IPv4地址字串,

示例

struct in_addr stAddr;
stSrcAddr.s_addr = inet_addr_small("192.168.0.9");
printf("%s\r\n", inet_ntoa(stAddr));

回傳目錄

inet_ntoa_ext

功能

注意,這是一個執行緒不安全的函式,實作4位元組無符號整型地址到點分十進制1Pv4地址的轉換,

原型

char *inet_ntoa_ext(in_addr_t unAddr); 

入口引數

  • unAddr:要轉換的IPv4地址,4位元組無符號整型格式

回傳值

回傳字串指標,指向轉換后的點分十進制格式的IPv4地址字串,

示例

in_addr_t unAddr = inet_addr_small("192.168.0.9");
printf("%s\r\n", inet_ntoa_ext(unAddr));

回傳目錄

inet_ntoa_safe

功能

注意,這是一個執行緒安全的函式,實作in_addr型別的地址到點分十進制1Pv4地址的轉換,

原型

char *inet_ntoa_safe(struct in_addr stInAddr, char *pszAddr); 

入口引數

  • stInAddr:指向in_addr型別的IPv4地址的指標
  • pszAddr:指向轉換后的點分十進制IPv4地址字串的指標

回傳值

回傳字串指標,指向轉換后的點分十進制格式的IPv4地址字串,其地址其實就是引數pszAddr指向的地址,

示例

CHAR szAddr[20];
struct in_addr stAddr;
stSrcAddr.s_addr = inet_addr_small("192.168.0.9");
printf("%s\r\n", inet_ntoa_safe(stAddr, szAddr));

回傳目錄

inet_ntoa_safe_ext

功能

注意,這是一個執行緒安全的函式,實作4位元組無符號整型地址到點分十進制1Pv4地址的轉換,

原型

char *inet_ntoa_safe_ext(in_addr_t unAddr, char *pszAddr); 

入口引數

  • unAddr:要轉換的IPv4地址,4位元組無符號整型格式
  • pszAddr:指向轉換后的點分十進制IPv4地址字串的指標

回傳值

回傳值為字串指標,指向轉換后的點分十進制格式的IPv4地址字串,其地址其實就是引數pszAddr指向的地址,

示例

CHAR szAddr[20];
in_addr_t unAddr = inet_addr_small("192.168.0.9");
printf("%s\r\n", inet_ntoa_safe_ext(unAddr, szAddr));

回傳目錄

ip_addressing

功能

比較兩個IPv4地址是否屬于同一網段,

原型

BOOL ip_addressing(in_addr_t un1stIp, in_addr_t un2ndIp, in_addr_t unGenmask); 

入口引數

  • un1stIp:第一個被比較的IPv4地址
  • un2ndIp:第二個被比較的IPv4地址
  • unGenmask:子網掩碼

回傳值

回傳TRUE表示在同一網段,FALSE則不屬于同一網段,

示例

回傳目錄

strtok_safe

功能

執行緒安全的strtok函式,

原型

CHAR *strtok_safe(CHAR **ppszStart, const CHAR *pszSplitStr); 

入口引數

  • ppszStart:指向下一個要被截取的字串片段的指標的指標
  • pszSplitStr:指向分隔符的指標

回傳值

回傳字串指標,指向下一個分隔符之前的字串;回傳值為NULL則截取完畢,

示例

CHAR szTestStr[64];
sprintf(szTestStr, "123;456;789,ABC;,EFG"); 
CHAR *pszStart = szTestStr; 
CHAR *pszItem = strtok_safe(&pszStart, ";"); 
while(NULL != pszItem)
{
    printf("%s\r\n", pszItem); 
    pszItem = strtok_safe(&pszStart, ";");
}

回傳目錄

snprintf_hex

功能

將16進制資料格式化為字串,

原型

void snprintf_hex(const UCHAR *pubHexData, USHORT usHexDataLen, CHAR *pszDstBuf, UINT unDstBufSize, BOOL blIsSeparate); 

入口引數

  • pubHexData:指向16進制資料的指標
  • usHexDataLen:16進制資料的長度
  • pszDstBuf:指向接識訓沖區的指標,其用于接收格式化后的字串
  • unDstBufSize:接識訓沖區的長度,單位:位元組
  • blIsSeparate:格式化后的字串在兩個16進制資料之間是否增加空格,即2A 1F還是2A1F

回傳值

示例

UCHAR ubHexData[16] = "\xAB\xCD\x2A\x1F\x3C\x4D";
CHAR szHexDataStr[64];
snprintf_hex(ubHexData, 6, szHexDataStr, 64, TRUE); 
printf("%s\r\n", szHexDataStr);

回傳目錄

printf_hex

功能

將16進制資料格式化為字串輸出到控制臺,

原型

void printf_hex(const UCHAR *pubHexData, USHORT usHexDataLen, UCHAR ubBytesPerLine); 

入口引數

  • pubHexData:指向16進制資料的指標
  • usHexDataLen:16進制資料的長度
  • ubBytesPerLine:每行固定輸出多少 位元組的資料,比如16位元組一行

回傳值

示例

UCHAR ubHexData[16] = "\xAB\xCD\x2A\x1F\x3C\x4D\xAA\x4E\xFE\x45\x6B\x9A\x05\x71\x8E\x1B\x52\x78";
printf_hex(ubHexData, 18, 16);

回傳目錄

onps_error

功能

將協議堆疊回傳的錯誤碼轉換成具體的描述字串,

原型

const CHAR *onps_error(EN_ONPSERR enErr); 

入口引數

  • enErr:錯誤編碼

回傳值

回傳值為字串指標,指向具體的錯誤描述字串的指標,

示例

回傳目錄

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/530496.html

標籤:嵌入式

上一篇:TEE學習(一) OP-TEE

下一篇:TEE學習(一) OP-TEE

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more