Socket資料傳輸

2021-08-09 05:33:29 字數 3559 閱讀 4398

socket配置

通過socket呼叫返回乙個socket描述符後,在使用socket進行網路傳輸以前,必須配置該socket。面向連線的socket客戶端通過呼叫connect函式在socket資料結構中儲存本地和遠端資訊。無連線socket的客戶端和服務端以及面向連線socket的服務端通過呼叫 bind函式來配置本地資訊。

bind函式將socket與本機上的乙個埠相關聯,隨後你就可以在該埠監聽服務請求。bind函式原型為:

int bind(int sockfd,struct sockaddr *my_addr, int addrlen);

sockfd是呼叫socket函式返回的socket描述符,my_addr是乙個指向包含有本機ip位址及埠號等資訊的sockaddr型別的指標;addrlen常被設定為sizeof(struct sockaddr)。

struct sockaddr結構型別是用來儲存socket資訊的:

struct sockaddr ;

sa_family一般為af_inet,代表internet(tcp/ip)位址族;sa_data則包含該socket的ip位址和埠號。

另外還有一種結構型別:

struct sockaddr_in ;

這個結構更方便使用。sin_zero用來將sockaddr_in結構填充到與struct sockaddr同樣的長度,可以用bzero()或memset()函式將其置為零。指向sockaddr_in 的指標和指向sockaddr的指標可以相互轉換,這意味著如果乙個函式所需引數型別是sockaddr時,你可以在函式呼叫的時候將乙個指向 sockaddr_in的指標轉換為指向sockaddr的指標;或者相反。

使用bind函式時,可以用下面的賦值實現自動獲得本機ip位址和隨機獲取乙個沒有被占用的埠號:

my_addr.sin_port = 0;

my_addr.sin_addr.s_addr = inaddr_any;

通過將my_addr.sin_port置為0,函式會自動為你選擇乙個未占用的埠來使用。同樣,通過將my_addr.sin_addr.s_addr置為inaddr_any,系統會自動填入本機ip位址。

注意在使用bind函式是需要將sin_port和sin_addr轉換成為網路位元組優先順序;而sin_addr則不需要轉換。

計算機資料儲存有兩種位元組優先順序:高位位元組優先和低位位元組優先。internet上資料以高位位元組優先順序在網路上傳輸,所以對於在內部是以低位位元組優先方式儲存資料的機器,在internet上傳輸資料時就需要進行轉換,否則就會出現資料不一致。

下面是幾個位元組順序轉換函式:

·htonl():把32位值從主機位元組序轉換成網路位元組序

·htons():把16位值從主機位元組序轉換成網路位元組序

·ntohl():把32位值從網路位元組序轉換成主機位元組序

·ntohs():把16位值從網路位元組序轉換成主機位元組序

bind()函式在成功被呼叫時返回0;出現錯誤時返回"-1"並將errno置為相應的錯誤號。需要注意的是,在呼叫bind函式時一般不要將埠號置為小於1024的值,因為1到1024是保留埠號,你可以選擇大於1024中的任何乙個沒有被占用的埠號。

連線建立

資料傳輸

send()和recv()這兩個函式用於面向連線的socket上進行資料傳輸。

send()函式原型為:

int send(int sockfd, const void *msg, int len, int flags);

sockfd是你想用來傳輸資料的socket描述符;msg是乙個指向要傳送資料的指標;len是以位元組為單位的資料的長度;flags一般情況下置為0(關於該引數的用法可參照man手冊)。

send()函式返回實際上傳送出的位元組數,可能會少於你希望傳送的資料。在程式中應該將send()的返回值與欲傳送的位元組數進行比較。當send()返回值與len不匹配時,應該對這種情況進行處理。

char *msg = "hello!";

int len, bytes_sent;

……len = strlen(msg);

bytes_sent = send(sockfd, msg,len,0);

……recv()函式原型為:

int recv(int sockfd,void *buf,int len,unsigned int flags);

sockfd是接受資料的socket描述符;buf 是存放接收資料的緩衝區;len是緩衝的長度。flags也被置為0。recv()返回實際上接收的位元組數,當出現錯誤時,返回-1並置相應的errno值。

sendto()和recvfrom()用於在無連線的資料報socket方式下進行資料傳輸。由於本地socket並沒有與遠端機器建立連線,所以在傳送資料時應指明目的位址。

sendto()函式原型為:

int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);

該函式比send()函式多了兩個引數,to表示目地機的ip位址和埠號資訊,而tolen常常被賦值為sizeof (struct sockaddr)。sendto 函式也返回實際傳送的資料位元組長度或在出現傳送錯誤時返回-1。

recvfrom()函式原型為:

int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);

from是乙個struct sockaddr型別的變數,該變數儲存源機的ip位址及埠號。fromlen常置為sizeof (struct sockaddr)。當recvfrom()返回時,fromlen包含實際存入from中的資料位元組數。recvfrom()函式返回接收到的位元組數或當出現錯誤時返回-1,並置相應的errno。

如果你對資料報socket呼叫了connect()函式時,你也可以利用send()和recv()進行資料傳輸,但該socket仍然是資料報socket,並且利用傳輸層的udp服務。但在傳送或接收資料報時,核心會自動為之加上目地和源位址資訊。

結束傳輸

當所有的資料操作結束以後,你可以呼叫close()函式來釋放該socket,從而停止在該socket上的任何資料操作:

close(sockfd);

你也可以呼叫shutdown()函式來關閉該socket。該函式允許你只停止在某個方向上的資料傳輸,而乙個方向上的資料傳輸繼續進行。如你可以關閉某socket的寫操作而允許繼續在該socket上接受資料,直至讀入所有資料。

int shutdown(int sockfd,int how);

sockfd是需要關閉的socket的描述符。引數 how允許為shutdown操作選擇以下幾種方式:

·0-------不允許繼續接收資料

·1-------不允許繼續傳送資料

·2-------不允許繼續傳送和接收資料,

·均為允許則呼叫close ()

shutdown在操作成功時返回0,在出現錯誤時返回-1並置相應errno。

udp的socket資料傳輸

關於socket的配置 1 建立sokcet套接字 2 為建立的socket繫結位址與埠,指定傳輸的協議,一般採用af inet,資料的傳輸格式一般為 sock stream sock dgram 3 開啟檔案識別符號,並開始傳送資料 udp客戶端code include include inclu...

C SFTP資料傳輸

我們有些客戶公司的資料比較重要,為了安全集團公司內部都使用的是區域網,但是有時候又不得不予外界網際網路做資料互動,所以有些不重要的系統是放在外界網際網路的,這樣以來內部系統和外部系統的資料互動就成為了問題,這樣以來就使用到了sftp伺服器來作為資料傳輸的中介。下面不說了,直接上c 此處使用了第三方動...

資料傳輸方式

資料傳輸方式 1 並行傳輸與序列傳輸 並行傳輸指的是資料以成組的方式,在多條並行通道上同時進行傳輸。常用的就是將構成一 個字元 的幾位二進位製碼,分別在幾個並行通道上進行傳輸。例如,採用8單位 的字 符 可以用8個通道並行傳輸。一次傳送乙個字元,因此收 發雙方不存在字元的同步問題,不需要另加 起 止...