1. 程式人生 > >一些基本問題:大小端,網路位元組序,socket程式設計函式的注意點,gdb和coredump除錯

一些基本問題:大小端,網路位元組序,socket程式設計函式的注意點,gdb和coredump除錯

1,什麼是大小端?

大小端是指資料在記憶體的的存放順序,現代計算機一次能夠載入32bit或者64bit的資料或者指令,因而資料的存放順序影響它被裝載到整數的值。以小端來講:低地址存資料的低位,高地址存資料的高;而大端敲好反過來:高地址存低位,地址存高位。

2.測試大小端

測試大小端最常用的方法是使用一個聯合體,定義成員為一個short和char然後給short型別變數賦值為1,看char變數是否也是1,如果是說明是小端,反之是大端。

#include<iostream>

using namespacestd;

int main()

{

      union et{

             short a;

             char b;

      };

      et t;

             t.a=1;

      if(t.b==1)

      {

             cout<<"小端"<<endl;

      }

      else

      {

             cout<<"大端"<<endl;

      }

      return 0;

}

3.網路位元組序是大端的,因此當從主機位元組序向網路位元組序進行轉換時需要根據本機的大小端進行轉換,主機端是小端,則向網路傳送資料時需要轉化為大端,主機本身是大端的就不必進行轉換了。再者介紹下面4個解決網路位元組序和主機位元組序轉換問題的函式、

一二均為host to network long主機位元組序long轉換為網路位元組序的long,第二個只不過是short之間的轉換而已。第三個和第四個是針對於net to host網路位元組序向主機位元組序的轉換(主機位元組序是小端)

4,listen

看函式宣告

Listen建立監聽佇列,將完成三次握手處於established狀態的連線放入監聽佇列中,listen的第二個引數就backlog就是用於指定核心監聽佇列的最大長度。當然這個長度包含了處於半連線狀態和完全連線狀態的socket的上限。當然現在版本的backlog只是代表處於完全連線狀態的socket的上限。處於半連線狀態syn_rcvd的上限值可以通過/proc/sys/net/ipv4/tcp_max_syn_backlog核心引數定義,其典型值是5。

Listen成功返回0,失敗返回-1,並設定errno.當然實際情況中處於完全連線狀態的並在佇列中的一般是backlog+1,不過這並不一定,但是實際處在完全連線上的socket要比backlog值要大

5.recv和send是專門面向tcp的read和write系統呼叫


它們都返回ssize_t有符號整數。Sockfd都是傳送要接收或者傳送的socket連線套接字,由accept返回得到,buf儲存從接收緩衝區讀取的資料或者是從要從buff的資料放入大發送快取區,二者的len都用於指定資料量的大小。最後的flag是對資料的收發進行額外的控制作用。

表示資料鏈路層持續監聽對方的迴應,直到得到答覆。它僅用於SOCK_DGRAM或者SOCK_RAW型別的socket

不檢視路由表(don’t route),直接將資料傳送給本地區域網絡內的主機,這表示傳送者確切直到目標主機就在本地網路上。


對於socket的本次操作是非阻塞的


告訴核心應用程式還有更多的資料要傳送,核心將超時等待新資料寫入TCP傳送緩衝區後一併傳送,這樣可以防止TCP傳送過多小的報文段,從而提高傳輸效率

往讀端關閉的管道或者套接字連線中的寫入資料時不引發SIGPIPE訊號

傳送或接受緊急資料

還有

MSG_PEEK窺視緩衝中的資料,此次讀操作不會導致這些資料被清除

MSG_WAITALL 讀取到指定位元組數才返回

返回值方面:

Recv>0接收成功,返回實際接收的位元組數;recv=-1接收失敗並設定errno,等於0說明對方斷開連線。

Send>0傳送成功,返回實際傳送的位元組數,=-1代表失敗,並設定errno

6time_wait狀態

Time_wait狀態存在的意義在於兩點

1.      將前面傳送的,未及時到達本端,但是現在到或者將來到的所有失效的資料包丟棄

2.      可靠的終止TCP連線:保證最後的fin以及對於fin的確定資訊被髮送和接收到,從而終止雙方的TCP連線。

如何解決time_wait?

使用setsockopt系統呼叫

Level設定成SOL_SOCKET,optname設定成SO_REUSEADDR,reuse設定成intreuse=1;,&reuse,最後是前面一個引數的長度sizeof(int),經過setsockopt設定之後即使處於time_wait的socket繫結的地址也可以立即被複用,

方法二:修改核心引數/proc/sys/net/ipv4/tcp_tw_recycle來快速複用原來被繫結的socket地址。

7.accept呼叫

listen監聽佇列中接收一個連線,但是它只負責從監聽佇列中讀取連線,但是不關心連線處於何種狀態。比如說在客戶端和伺服器斷開連線之後,強行將這個連線中斷,並在一會回覆連線,會發現accept還是會正常返回,也就是說它對於網路環境的好壞義務所知,只是從佇列裡面去一取出一個連線並返回即可,對取出的連線套接字的狀態是不關心的。

 

Sockfd是本端的套接字,addr用於存放被接收連線的遠端sock的地址資訊,該地址長度len,accept成功返回一個新的sockfd用於唯一標識被接受的這個連線,伺服器可以通過讀寫該新的套接字與遠端客戶端進行通訊。

 Coredump除錯

Coredump除錯的原因:gdb除錯效率較低時可以使用coredump核心轉儲檔案進行除錯。

首先編寫一段帶有segment falut的程式碼

遠行發現報錯

使用ulimit檢視一下資訊

將core file size設定成unlimited

再次編譯並加入除錯選項-g,並執行程式,得到結構段錯誤的同時還將核心轉儲了

使用gdb sg(被除錯的可執行檔案) core檔案,得出詳細的錯誤資訊,非常之方便的就找到了錯誤出現的地方

最後通過設定ulimit的選項可以生成不同的檔案進行除錯,具體流程與coredump差不多。

gdb除錯依賴於gcc在編譯連結生成elf可執行檔案的除錯資訊,產生除錯資訊,需要在gcc命令最後加上-g選項,如上面的gcc sg_fault.c –o sg –g

p var列印一個變數var的地址

bt檢視堆疊呼叫情況

b n在第n行插入斷點

s 進入一個函式或者過程

display var列印被跟蹤的變數的值

n用於單步執行

l n顯示從n行開始的程式碼

thread info多執行緒除錯

thread id切換到執行緒id中去

常用就這些,再多就去手冊查。。。。