導航:首頁 > 編程系統 > linuxsocket面試

linuxsocket面試

發布時間:2023-05-19 15:06:48

linux下的 socket編程問題!

第一個問題:

對,是那樣的,用open打開文件,用read讀取文件,在發送給對方,接收方接收到後,寫入文件就可以了。不過在這個過程中最好別用字元串函數,除非你很熟悉。

第二個問題

首先你得去搞清楚什麼是線程,什麼是進程,fork出來的叫進程,pthread_create出來的才叫線程。伺服器有很多種模型(多進程,多線程,select,epoll模型,這個我的blog上有,famdestiny.cublog.cn),不一定要用多進程。

給你寫了個代碼,自己先看看:

注意,在自己的目錄下創建一個叫pserverb的文件,程序會把這個文件復製成test文件。你可以自己根據需要改改

server:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define SERV_PORT 5358
#define MAX_CONN 10
#define BUF_LEN 1024

void str_echo(FILE *fp, int sockfd){
ssize_t nread;
int file_fd;
char buf[BUF_LEN] = {0};

file_fd = open("test", O_WRONLY | O_TRUNC | O_CREAT, 0755);
while(1) {
bzero(buf, BUF_LEN);
if((nread = read(sockfd, buf, BUF_LEN)) == -1) {
if(errno == EINTR) {
continue;
}
else {
printf("readn error: %s\n", strerror(errno));
continue;
}
}
else if (nread == 0) {
break;
}
else {
printf("%s\n", buf);
write(file_fd, buf, nread);
}
}
close(file_fd);
}

void sig_chld(int sig){
pid_t pid;
int state;
while((pid = waitpid(-1, &state, WNOHANG)) > 0){
printf("child process %d exited.", pid);
}
return;
}

int main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t cliaddrlen;
pid_t childpid;
struct sockaddr_in servaddr, cliaddr;

if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
printf("socket error: %s\n", strerror(errno));
return 0;
}

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){
printf("bind error: %s\n", strerror(errno));
return 0;
}

if(listen(listenfd, MAX_CONN) == -1){
printf("listen error: %s\n", strerror(errno));
return 0;
}

signal(SIGCHLD, sig_chld);

while(1){
cliaddrlen = sizeof(cliaddr);
if((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen)) == -1){
if(errno == EINTR){
continue;
}
else{
printf("accept error: %s\n", strerror(errno));
continue;
}
}

if((childpid = fork()) == 0){
close(listenfd);
str_echo(stdin, connfd);
exit(0);
}
else if(childpid > 0){
close(connfd);
}
else{
printf("fork error!\n");
continue;
}
}
}

client:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define SERV_ADDR "127.0.0.1"
#define SERV_PORT 5358
#define BUF_LEN 1024

void str_cli(char *path, int sockfd)
{
char sendbuf[BUF_LEN] = {0};
int fd, n;

if((fd = open("./pserverb", O_RDONLY)) == -1){
printf("%s\n", strerror(errno));
exit(0);
}
while((n = read(fd, sendbuf, BUF_LEN)) != 0) {
if(n < 0){
printf("%s\n", strerror(errno));
exit(0);
}
write(sockfd, sendbuf, n);
bzero(sendbuf, BUF_LEN);
}
close(fd);
return;
}

int main(int argc, char **argv)
{
int fd;
struct sockaddr_in servaddr;

fd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(SERV_ADDR);
servaddr.sin_port = htons(SERV_PORT);

if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("connect error: %s\n", strerror(errno));
return 0;
}

str_cli(argv[1], fd);
return 0;
}

㈡ linux下socket編程初級問題,求助,急

你設斷點查吧,我一下也看不出來

㈢ 面試必備:Binder進程通信原理

先簡單概括性地說說Linux現有的所有進程間IPC方式:
管道(Pipe): 在創建時分配一個page大小的內存,緩存區大小比較有限;
消息隊列(Message): 信息復制兩次,額外的CPU消耗;不適合頻繁或信息量大的通信;
共享內存(Share Memory): 無須復制,共享緩沖區直接附加到進程虛擬地址空間,速度快;但進程間的同步問題操作系統無法實現,必須各進程利用同步工具解決。
套接字(Socket): 作為更通用的介面,傳輸效率低,主要用於不同機器或跨網路的通信。
信號量(Semaphore): 常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此主要作為進程間以及同一進程內不模鬧同線程之間的同步手段。
信號(Signal): 不適用於信息交換,更適用於進程中斷控制,比如非法內存訪問、殺死某個進程等。

從4個角度來展開對Binder的分析
(1)從性能的角度
數據拷貝次數: Binder數據拷貝只需要一次,而管道、消息隊列、套接字都需要2次,但共享內存方式一次內存拷貝都不需要;從性能角度看,Binder性能僅次於共享內存。
(2)從穩定性的角度
    Binder是基於C/S架構的,架構清晰明朗,Server端和Client端相對獨立,穩定性較好;而共享內存實現方式復雜,沒有Client端與Server端之別,需要充分考慮到訪問臨界資源的並發同步問題,否則可能會出現死鎖等問題;從穩定性角度看,Binder架構優越於共享內存。
(3)從安全的角度
    傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身旦搭罩份;而Android作為一個開放的開源體系,手機安全顯得額外重要,傳統Linux IPC五任何保護措施,完全由上層協議來確保。
    Android為每個安裝好的應用程序分配了自己的UID,故進程的UID是鑒別進程身份的重要標志。前面提到C/S架構, Android系統中對外只暴露Client端,Client端將任務發送給Server端,Server端會根據許可權控制策略,判斷UID/PID是否滿足訪問許可權,目前許可權控制很多時候是通過彈出許可權詢問對話框,讓用戶選擇是否運行。
    傳統IPC只能由用戶在數據包里填入UID/PID;另外,可靠的身份標記只有由IPC機制本身在內核中添加。其次傳統IPC訪問接入點是開發的,無法建立私有通道。從安全形度,Binder的安全性更高。
(4)從語言層面的角度
    大家都知道Linux是基於C語言(面向過程的語言),而Android是基於Java語言(面向對象的語句)。Binder恰枝液恰符合面向對象思想,將進程間通信轉化為對某個Binder對象的引用,調用該對象的方法。而其獨特之處在於Binder對象是一個可以跨進程引用的對象,它的實體位於一個進程,而它的引用卻遍布於系統的各個進程之中。Binder模糊了進程邊界,淡化了進程間通信過程,讓整個系統彷彿運行於同一個面向對象的程序之中。

    Binder框架定義了四個角色:Server,Client,ServiceManager(以後簡稱SM)以及Binder驅動。其中Server,Client,SM運行於用戶空間,驅動運行於內核空間。

ServiceManager與實名Binder

Client獲得實名Binder的引用
    Server向SM注冊了Binder實體及其名字後,Client就可以通過名字獲得該Binder的引用了。

匿名Binder
    並不是所有Binder都需要注冊給SM廣而告之的。Server端可以通過已經建立的Binder連接將創建的Binder實體傳給Client,當然這條已經建立的Binder連接必須是通過實名Binder實現。由於這個Binder沒有向SM注冊名字,所以是個匿名Binder。Client將會收到這個匿名Binder的引用,通過這個引用向位於Server中的實體發送請求。匿名Binder為通信雙方建立一條私密通道,只要Server沒有把匿名Binder發給別的進程,別的進程就無法通過窮舉或猜測等任何方式獲得該Binder的引用,向該Binder發送請求。

     傳統IPC方式中,數據是怎樣從發送端到達接收端的呢? 通常的做法是: 發送方 將准備好的數據存放在緩存區中,通過系統API調用進入 內核 中。 內核服務程序 在內核空間分配內存,將數據從 發送方 緩存區復制到內核緩存區中。 接收方 讀數據是也要提供一塊緩存區, 內核 將數據從內核緩存區拷貝到 接收方 提供的緩存區中並喚醒接收線程,完成一次數據發送。這種存儲-轉發機制有兩個缺陷:首先是效率低下,需要做兩次拷貝(用戶空間->內核空間->用戶空間)。Linux使用_from_user()和_to_user()實現這兩個跨空間拷貝。其次是接收數據的緩存要由接收方提供,可接收方不知道到底要多大的緩存才夠用。只能開辟盡量打的空間或先調用API接收消息頭獲得消息體大小,再開辟適當的空間接收消息體。兩種做法都有不足,不是浪費空間就是浪費時間。
     Binder採用一種全新策略:由Binder驅動負責管理數據接收緩存。 Binder驅動通過實現mmap()來創建數據接收的緩存空間。

    這樣Binder的接收方就有了一片大小為MAP_SIZE的接收緩存區。mmap()的返回值是內存映射在用戶空間的地址,不過這段空間是由驅動管理,用戶不必直接訪問(映射類型為PROT_READ,只讀映射)。

參考文獻
Android Binder機制原理(史上最強理解,沒有之一)

㈣ Linux Socket編程求助啊,一個伺服器和多個客戶端通信問題求助

如果客戶端並發連接數不是很大,比如50個以下,可以用如下模型:

  1. 建立一個監聽主線程,循環監聽埠。

  2. 當有客戶端連接時,建立客戶端通訊線程,並保留客戶端socket到鏈表中。

  3. 當客戶端斷開連接時,從socket鏈表中刪除該socket。


㈤ linux 下的socket怎麼測試是否成功

增加對Linux socket連接 最近的一個項目的最大連接數是模擬多個套接字的客戶端和伺服器之間的通信。 Linux系統由於Linux的限制,/在include / linux / posix_types.h文件中有如下的宏定義: #UNDEF __FD_SETSIZE 的#define __FD_SETSIZE 1024 這個宏是當你需要超亮梁過1024個FD,如select()函數將監聽錯誤定義的最大文件描述符1024。所以,你需要改變1024所需要的數量,但不超過65,535。但這是不夠的僅僅。 第二步你需要的文件的進程敬耐運打開的最大數量。具體的步驟是: 1,CD /usr/src/linux-2.4/include/linux 2,六limits.h中編輯文件: 的#define NR_OPEN 90240原1024 1024 的#define OPEN_MAX 10240原值 3值,六fs.h文件 的#define INR_OPEN 10240原值1024 的#define NR_FILE 65536 8192原始值,內存64 / 1M比例計算的值,1G內存的計算公式為:64 * 10. 4 1024 的#define NR_RESERVED_FILES 128原值,CD /usr/src/linux-2.4/include/net BR>五,六tcp.h中 的#define TCP_LHTABLE_SIZE的32 128原值易聽聽隊列,建立大。 - 設為與內存相關的打開文件的最大數量,系統會減慢太多。 第三步是編畝瞎譯內核,具體步驟是: 1.使清潔 2.化妝 3. make dep的 4.做的bzImage 將導入的bzImage /啟動重新啟動系統! wc命令,以目前在建立套接字連接數統計| 與超過1024個客戶端和伺服器到伺服器的終端使用netstat的連接。

㈥ 簡述linux下,從socket寫入和讀取的函數,read/write和send/recv函數的含義並解釋其介面意義簡答題

Ssize_t write(int fd,const void *buf,size_t nbytes);
write的返回值大於0,表示寫了部分數據或者是全部的數據,這樣用一個while循環不斷的寫入數據,但是循環過程中的buf參數和nbytes參數是我們自己來更新的,返回值小於0,此時出錯了,需要根據錯誤類型進行相應的處理
Ssize_t read(int fd,void *buf,size_t nbyte)
Read函數是負責從fd中讀取內容,當讀取成功時,read返回實際讀取到的位元組數,如果返回值是0,表示已經讀取到文件的結束了,小於0表示是讀取錯誤。
Recv函數和send函數
Recv函數和read函數提供了read和write函數一樣的功能,不同的是他們提供了四個參數。
Int
recv(int fd,void *buf,int len,int flags)
Int
send(int fd,void *buf,int len,int flags)
前面的三個參數和read、write函數是一樣的。第四個參數可以是0或者是一下組合:
MSG_DONTROUTE:不查找表
是send函數使用的標志,這個標志告訴IP,目的主機在本地網路上,沒有必要查找表,這個標志一般用在網路診斷和路由程序裡面。
MSG_OOB:接受或者發生帶外數據
表示可以接收和發送帶外數據。
MSG_PEEK:查看數據,並不從系統緩沖區移走數據
是recv函數使用的標志,表示只是從系統緩沖區中讀取內容,而不清楚系統緩沖區的內容。這樣在下次讀取的時候,依然是一樣的內容,一般在有過個進程讀寫數據的時候使用這個標志。
MSG_WAITALL:等待所有數據
是recv函數的使用標志,表示等到所有的信息到達時才返回,使用這個標志的時候,recv返回一直阻塞,直到指定的條件滿足時,或者是發生了錯誤。

㈦ Linux下socket並發連接數怎麼設置

並發socket連接數的多少決定於系統資源的多少,沒有一個常值的.在實際開發或者linux系統管理中也會根據需要進行相應的設置.
1.一般來說每一個網路連接,都會建立相應的socket句柄,同時每個連接也會有標准輸入輸出等基本的文件文件句柄,而且每一個socket連接都是進行文件操作的,因此連接數決定於系統資源.

2.Linux上一般可以通過ulimit來進行相應的資源限制,默認能打開的文件描述符自己可以查看.如下圖所示:

3.ulimit的命令格式:ulimit [-acdfHlmnpsStvw] [size]
參數說明:
-H 設置硬資源限制.
-S 設置軟資源限制.
-a 顯示當前所有的資源限制.
-c size:設置core文件的最大值.單位:blocks
-d size:設置數據段的最大值.單位:kbytes
-f size:設置創建文件的最大值.單位:blocks
-l size:設置在內存中鎖定進程的最大值.單位:kbytes
-m size:設置可以使用的常駐內存的最大值.單位:kbytes
-n size:設置內核可以同時打開的文件描述符的最大值.單位:n
-p size:設置管道緩沖區的最大值.單位:kbytes
-s size:設置堆棧的最大值.單位:kbytes
-t size:設置CPU使用時間的最大上限.單位:seconds
-v size:設置虛擬內存的最大值.單位:kbytes
-u <程序數目> 用戶最多可開啟的程序數目

㈧ 面試筆記-Socket MQTT Websocket

1.Socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個調用介面(API),通過Socket,我們才能使用TCP/IP協議。
2.MQTT協議是應用層協議不依賴長連接,適合弱網路。通過topic緩存信息。符合物聯網設備的使用場景。因為通過topic緩存信息,因此可以實現通過topic與多個端的一對多連接,而不是設備與設備的多對多連接,節省了能耗及帶寬。
MQTT的心跳,及非信息的報文,較Websocket更少,更節省帶寬及能耗。更適用於物理網的多種網路協議。
3.WebSocket和Http一樣在應用層,提供使用一個TCP連接進行雙向通訊的機制,包括網路協議和API,以取代網頁和伺服器採用HTTP輪詢進行雙向通訊的機制。 本質上來說,WebSocket是不限於HTTP協議的,但是由於現存大量的HTTP基礎設施,代理,過濾,身份認證等等,WebSocket借用HTTP和HTTPS的埠。由於使用HTTP的埠,因此TCP連接建立後的握手消息是基於HTTP的,由伺服器判斷這是一個HTTP協議,還是WebSocket協議。 WebSocket連接除了建立和關閉時的握手,數據傳輸和HTTP沒丁點關系了。

Socket 連接,至少需要一對套接字,分為 clientSocket,serverSocket 連接分為3個步驟:

(1) 伺服器監聽:伺服器並不定位具體客戶端的套接字,而是時刻處於監聽狀態;
(2) 客戶端請求:客戶端的套接字要描述它要連接的伺服器的套接字,提供地址和埠號,然後向伺服器套接字提出連接請求;
(3) 連接確認:當伺服器套接字收到客搭頃飢戶端套接字發來的請求後,就響應客知返戶端套接字的請求,並建立一個新的線程,把伺服器端的套接字的描述發給客戶端。一旦客戶端確認了此描述,就正式建立連接。而伺服器套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求.
Socket為長連接:通常情況下Socket 連接就是 TCP 連接,因此 Socket 連接一旦建立,通訊雙方開始互發數據內容,直到雙方斷開連接。在實際應用中,由於網路節點過多,在傳輸過程中,會被節點斷開連接,因此要通過輪詢高速網路,該節點處於活躍狀態。

很多情況下,都乎缺是需要伺服器端向客戶端主動推送數據,保持客戶端與服務端的實時同步。
若雙方是 Socket 連接,可以由伺服器直接向客戶端發送數據。
若雙方是 HTTP 連接,則伺服器需要等客戶端發送請求後,才能將數據回傳給客戶端。
因此,客戶端定時向伺服器端發送請求,不僅可以保持在線,同時也詢問伺服器是否有新數據,如果有就將數據傳給客戶端。

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是輕量級基於代理的發布/訂閱的消息傳輸協議,設計思想是開放、簡單、輕量、易於實現。這些特點使它適用於受限環境。
例如:
①網路代價昂貴,帶寬低、不可靠。
②在嵌入設備中運行,處理器和內存資源有限。
該協議的特點有:
①使用發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合。 ②對負載內容屏蔽的消息傳輸。
③使用 TCP/IP 提供網路連接。
④有三種消息發布服務質量:
⑤"至多一次",消息發布完全依賴底層 TCP/IP 網路。會發生消息丟失或重復。這一級別可用於如下情況,環境感測器數據,丟失一次讀記錄無所謂,因為不久後還會有第二次發送。
⑥"至少一次",確保消息到達,但消息重復可能會發生。
⑦"只有一次",確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。
⑧小型傳輸,開銷很小(固定長度的頭部是 2 位元組),協議交換最小化,以降低網路流量。
⑨使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制。

實現MQTT協議需要客戶端和伺服器端通訊完成,在通訊過程中,MQTT協議中有三種身份:發布者(Publish)、代理(Broker)(伺服器)、訂閱者(Subscribe)。其中,消息的發布者和訂閱者都是客戶端,消息代理是伺服器,消息發布者可以同時是訂閱者。

有三種消息發布服務質量:

「至多一次」,消息發布完全依賴底層TCP/IP網路。會發生消息丟失或重復。這一級別可用於如下情況,環境感測器數據,丟失一次讀記錄無所謂,因為不久後還會有第二次發送。這一種方式主要普通APP的推送,倘若你的智能設備在消息推送時未聯網,推送過去沒收到,再次聯網也就收不到了。qos=0

「至少一次」,確保消息到達,但消息重復可能會發生。qos=1

「只有一次」,確保消息到達一次。在一些要求比較嚴格的計費系統中,可以使用此級別。在計費系統中,消息重復或丟失會導致不正確的結果。這種最高質量的消息發布服務還可以用於即時通訊類的APP的推送,確保用戶收到且只會收到一次。qos=2

Topic,可以理解為消息的類型,訂閱者訂閱(Subscribe)後,就會收到該主題的消息內容(payload);

payload,可以理解為消息的內容,是指訂閱者具體要使用的內容。

在MQTT協議中,一個MQTT數據包由:固定頭(Fixed header)、可變頭(Variable header)、消息體(payload)三部分構成。MQTT數據包結構如下:

固定頭(Fixed header)。存在於所有MQTT數據包中,表示數據包類型及數據包的分組類標識。
可變頭(Variable header)。存在於部分MQTT數據包中,數據包類型決定了可變頭是否存在及其具體內容。
消息體(Payload)。存在於部分MQTT數據包中,表示客戶端收到的具體內容。

WebSocket則提供使用一個TCP連接進行雙向通訊的機制,包括網路協議和API,以取代網頁和伺服器採用HTTP輪詢進行雙向通訊的機制。 本質上來說,WebSocket是不限於HTTP協議的,但是由於現存大量的HTTP基礎設施,代理,過濾,身份認證等等,WebSocket借用HTTP和HTTPS的埠。由於使用HTTP的埠,因此TCP連接建立後的握手消息是基於HTTP的,由伺服器判斷這是一個HTTP協議,還是WebSocket協議。 WebSocket連接除了建立和關閉時的握手,數據傳輸和HTTP沒丁點關系了。 由此可知兩者的應用場景不一樣: MQTT是為了物聯網場景設計的基於TCP的Pub/Sub協議,有許多為物聯網優化的特性,比如適應不同網路的QoS、層級主題、遺言等等。 WebSocket是為了HTML5應用方便與伺服器雙向通訊而設計的協議,HTTP握手然後轉TCP協議,用於取代之前的Server Push、Comet、長輪詢等老舊實現。 兩者之所有有交集,是因為一個應用場景:如何通過HTML5應用來作為MQTT的客戶端,以便接受設備消息或者向設備發送信息,那麼MQTT over WebSocket自然成了最合理的途徑了。

㈨ 面試時怎麼教熟悉linux網路編程

不知你的水平處於哪個階段,假如你是學嵌入式的,剛開始接觸我建議你看華清遠見寫的《嵌入式Linux應用程序開發》雖然這本書上的好多是從後面我要說的書上抄的(嘿嘿,技術嗎不能完全這樣說)原因是:比較適合初學者,教材適合自己的才是王道,不能讓小學生成天看牛津高級詞典,一下子把人就嚇住,剛開始要學的不要太多 不要指望一下子就明白全部,太厚的書,太全了 也太多,當然這個只是說你的水平在初級階段

水平還行就看看國外的經典教材,當然是 W.Richard Stevens老人家寫的經典3部(可惜他老人家現在走了 不能給我們再寫經典 太可惜了)
1)Advanced Programming In The UNIX Environment 中文翻譯名為《UNIX環境高級編程》譯者:尤晉元,翻譯的還行(在這里我要批評有些人成天給翻譯的書挑刺 老說某某翻譯的不好 甚至打罵,我說一句:有本事你看英文版行了,英語不行就不要叫,再說你自己看了多少,也許你只是成天跟著吆喝的人)
2)Unix Network Programing 中文翻譯名為《UNIX網路編程》有兩卷 清華大學,誰翻譯的 呵呵 沒注意
第一卷講BSD Socket網路編程介面和另外一種網路編程介面的,不過現在一般都用BSD Socket,所以這本書只要看大約一半多就可以了。第二卷沒有設計到網路的東西,主要講進程間通訊和Posix線程。所以看了《UNIX環境高級編程》以後,就可以看它了,基本上系統的東西就由《UNIX環境高級編程》和《UNIX網路編程》vol2概括了。看過《UNIX網路編程》以後,您就會知道系統編程的絕大部分編程技巧,即使卷一是講網路編程的。
3)《TCP/IP祥解》一共三卷,卷一講協議,卷二講實現,卷三講編程應用。我沒有怎麼看過。,但是據說也很經典的,因為我沒有時間看卷二,所以不便評價。

㈩ linux socket是什麼意思

socket介面是TCP/IP網路的API,socket介面定義了許多函數或常式,程序員可以用它們來開發TCP/IP網路上的應用程序。要學Internet上的TCP/IP網路編程,必須理解socket介面。
socket介面設計者最先是將介面放在Unix操作系統裡面的。如果了解Unix系統的輸入和輸出的話,就很容易了解socket了。網路的 socket數據傳輸是一種特殊的I/O,socket也是一種文件描述符。socket也具有一個類似於打開文件的函數調用socket(),該函數返回一個整型的socket描述符,隨後的連接建立、數據傳輸等操作都是通過該socket實現的。常用的socket類型有兩種:流式socket (SOCK_STREAM)和數據報式socket(SOCK_DGRAM)。流式是一種面向連接的socket,針對於面向連接的TCP服務應用;數據報式socket是一種無連接的socket,對應於無連接的UDP服務應用。
socket建立
為了建立socket,程序可以調用socket函數,該函數返回一個類似於文件描述符的句柄。socket函數原型為:
int socket(int domain, int type, int protocol); domain指明所使用的協議族,通常為PF_INET,表示互聯網協議族(TCP/IP協議族);type參數指定socket的類型: SOCK_STREAM 或SOCK_DGRAM,socket介面還定義了原始socket(SOCK_RAW),允許程序使用低層協議;protocol通常賦值 "0"。 socket()調用返回一個整型socket描述符,你可以在後面的調用使用它。
socket描述符是一個指向內部數據結構的指針,它指向描述符表入口。調用socket函數時,socket執行體將建立一個socket,實際上 "建立一個socket"意味著為一個socket數據結構分配存儲空間。socket執行體為你管理描述符表。 兩個網路程序之間的一個網路連接包括五種信息:通信協議、本地協議地址、本地主機埠、遠端主機地址和遠端協議埠。socket數據結構中包含這五種信息。
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 {
unsigned short sa_family; /*地址族,AF_xxx*/ char sa_data[14]; /*14位元組的協議地址*/ };
sa_family一般為AF_INET,代表Internet(TCP/IP)地址族;sa_data則包含該socket的IP地址和埠號。 另外還有一種結構類型: struct sockaddr_in {
short int sin_family; /*地址族*/
unsigned short int sin_port; /*埠號*/ struct in_addr sin_addr; /*IP地址*/
unsigned char sin_zero[8];/*填0保持與sockaddr同樣大小*/ };
這個結構更方便使用。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; /* 填入本機IP地址*/

通過將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中的任何一個沒有被佔用的埠號。
連接建立
面向連接的客戶程序使用connect函數來配置socket並與遠端伺服器建立一個TCP連接,其函數原型為:
int connect(int sockfd, struct sockaddr*serv_addr,int addrlen); Sockfd 是socket函數返回的socket描述符;serv_addr是包含遠端主機IP地址和埠號的指針;addrlen是遠端地質結構的長度。 connect函數在出現錯誤時返回-1,並且設置errno為相應的錯誤碼。
進行客戶端程序設計無須調用bind(),因為這種情況下只需知道目的機器的IP地址,而客戶通過哪個埠與伺服器建立連接並不需要關心,socket執行體為你的程序自動選擇一個未被佔用的埠,並通知你的程序數據什麼時候到達埠。
connect函數啟動和遠端主機的直接連接。只有面向連接的客戶程序使用socket時才需要將此socket與遠端主機相連。無連接協議從不建立直接連接。面向連接的伺服器也從不啟動一個連接,它只是被動的在協議埠監聽客戶的請求。
listen函數使socket處於被動的監聽模式,並為該socket建立一個輸入數據隊列,將到達的服務請求保存在此隊列中,直到程序處理它們。 int listen(int sockfd, int backlog);
Sockfd 是socket系統調用返回的socket 描述符;backlog指定在請求隊列中允許的最大請求數,進入的連接請求將在隊列中等待accept()它們(參考下文)。Backlog對隊列中等待服務的請求的數目進行了限制,大多數系統預設值為20。如果一個服務請求到來時,輸入隊列已滿,該socket將拒絕連接請求,客戶將收到一個出錯信息。
當出現錯誤時listen函數返回-1,並置相應的errno錯誤碼。
accept()函數讓伺服器接收客戶的連接請求。在建立好輸入隊列後,伺服器就調用accept函數,然後睡眠並等待客戶的連接請求。 int accept(int sockfd, void*addr, int*addrlen);
sockfd是被監聽的socket描述符,addr通常是一個指向sockaddr_in變數的指針,該變數用來存放提出連接請求服務的主機的信息(某台主機從某個埠發出該請求);addrten通常為一個指向值為sizeof(struct sockaddr_in)的整型指針變數。出現錯誤時accept函數返回-1並置相應的errno值。 首先,當accept函數監視的 socket收到連接請求時,socket執行體將建立一個新的socket,執行體將這個新socket和請求連接進程的地址聯系起來,收到服務請求的初始socket仍可以繼續在以前的 socket上監聽,同時可以在新的socket描述符上進行數據傳輸操作。 數據傳輸
send()和recv()這兩個函數用於面向連接的socket上進行數據傳輸。 int send(int sockfd, const void*msg, int len, int flags);
Sockfd是你想用來傳輸數據的socket描述符;msg是一個指向要發送數據的指針;Len是以位元組為單位的數據的長度;flags一般情況下置為0(關於該參數的用法可參照man手冊)。
send()函數返回實際上發送出的位元組數,可能會少於你希望發送的數據。在程序中應該將send()的返回值與欲發送的位元組數進行比較。當send()返回值與len不匹配時,應該對這種情況進行處理。
int recv(int sockfd,void*buf,int len,unsigned int flags);

閱讀全文

與linuxsocket面試相關的資料

熱點內容
gee引擎更新系統找不到指定文件 瀏覽:802
貝殼網的數據刪除了如何找回 瀏覽:509
華為榮耀6x怎麼切換網路 瀏覽:418
手機里的pdf文件在哪放 瀏覽:889
java版貪吃蛇畢業論文 瀏覽:989
微信公共號郵箱 瀏覽:415
圖片寬度代碼 瀏覽:460
有哪些好用的相見恨晚的app 瀏覽:664
cs部分文件找不到 瀏覽:369
小工工具 瀏覽:681
pat文件怎麼做 瀏覽:744
opensuse11內核版本 瀏覽:62
java後台校驗框架 瀏覽:379
編程怎麼做3d生存游戲 瀏覽:955
word使用教程下載 瀏覽:295
電腦文件平鋪圖片默認大小 瀏覽:115
文件查看設置信息失敗 瀏覽:668
編程如何編出烏鴉喝水的課文 瀏覽:20
國家反詐app報案助手怎麼使用 瀏覽:439
秘密文件丟失多少天 瀏覽:237

友情鏈接