sockets(套接字)程式設計有三種,流式套接字(sock_stream),資料報套接字(sock_dgram),原始套接字(sock_raw);基於tcp的socket程式設計是採用的流式套接字。在這個程式中,將兩個工程新增到乙個工作區。要鏈結乙個ws2_32.lib的庫檔案。
伺服器端程式設計的步驟:
1:載入套接字型檔,建立套接字(wsastartup()/socket());
2:繫結套接字到乙個ip位址和乙個埠上(bind());
3:將套接字設定為監聽模式等待連線請求(listen());
4:請求到來後,接受連線請求,返回乙個新的對應於此次連線的套接字(accept());
5:用返回的套接字和客戶端進行通訊(send()/recv());
6:返回,等待另一連線請求;
7:關閉套接字,關閉載入的套接字型檔(closesocket()/wsacleanup())。
客戶端程式設計的步驟:
1:載入套接字型檔,建立套接字(wsastartup()/socket());
2:向伺服器發出連線請求(connect());
3:和伺服器端進行通訊(send()/recv());
4:關閉套接字,關閉載入的套接字型檔(closesocket()/wsacleanup())。
函式介紹:
1.#include
int socket (int family, int type, int protocol);
返回值,成功為非負整數,成為套介面描數字;出錯為-1、
family引數:
af_inet --ipv4;
af_inet6--ipv6;
af_local--unix域協議;
af_route--路由socket;
af_key--金鑰socket;
type引數:
sock_stream--位元組流套介面
sock_dgram--資料報套介面
sock_ram--原始套介面
protocal引數一般置為0,當type為sock_ram時不同
2.#include
int connect (int sockfd, const struct sockaddr* servaddr, socklen_t addlen);
返回值,0-成功;-1-出錯;
servaddr引數可以為sockaddr_in和sockaddr_in6型別,但是都必須強制轉化為sockaddr指標型別;
connect函式的出錯處理:
(1)etimeout-connection timed out 目的主機不存在,沒有返回任何相應,例如主機關閉
(2)econnrefused-connection refused(硬錯)到達目的主機後,由於各種原因建立不了連線,主機返回rst(復位)響應,例如主機監聽程序未啟用,tcp取消連線等
(3)ehosttunreach-no route to host(軟錯)路由上引發了乙個目的地不可達的icmp錯誤
其中(1)(3),客戶端會進行定時多次重試,一定次數後才返回錯誤。另外,當connect連線失敗時,sockfd套介面不可用,必須關閉後重新socket分配才行。
3.#include
int bind (int sockfd, const struct sockaddr *addr, socklen_ t addrlen);
bind函式為套介面分配乙個本地位址和埠
對於tcp協議,本地ip和埠可以不指定,主機會自動分配!
一般來說,我們會給伺服器指定乙個監聽位址結構,以讓客戶端可以建立連線;連線建立後再分配乙個臨時埠作為資料傳輸通道。
而對於客戶端來說,一般不bind本地位址,而是讓核心根據輸出協議自動選定本地ip和埠。
當ip位址和埠設定為萬用字元時,表示由核心自動分配:
(1)對於埠,設定為0表示萬用字元
(2)ip位址,對於ipv4,萬用字元表示如下:
struct sockaddr_in scr;
scr.sin_addr.s_addr=htonl (inaddr_any);
對於ipv6,萬用字元表示如下:
struct sockaddr_in6 scr;
scr.sin6_addr=in6addr_any;
4.#include
int listen (int sockfd, int backlog);
backlog為最大連線個數,包括正在建立的連線和已經建立但是還未進行accept函式的連線,即處於三次握手機制和accept函式之間。
listen函式將sockfd套介面由主動模式變成被動監聽模式,使核心能接受指向此套介面的連線請求 。
當佇列已滿時,伺服器不會對新來的syn有任何回應(包括rst),從而使得客戶端延時重發syn。
5.#include
int accept (int sockfd, struct sockaddr * addr, socklen_t *len);
成功,返回非負描數字,稱為已連線套介面;-1表示出錯
sockfd為listen函式後的監聽套介面;
addr和len引數都為 值-結果 引數;
addr返回客戶程序的協議位址,功能類似getpeername函式
len引數呼叫前是addr的長度,返回後是核心讀取的addr結構的準確位元組數。
如果對客戶程序不感興趣,addr`len可設為null;
accept函式返回乙個由核心自動生成的新描述字,稱為 已連線套介面;
一般來說,sockfd稱為監聽套介面,在伺服器程序一直存在;accept返回的已連線套介面,在伺服器子程序中存在,一旦子程序連線結束,此套介面也關閉。
6.通常的處理,伺服器當程序accept後,會fork乙個子程序,同時,父程序關閉已連線套介面,子程序關閉監聽套介面,這樣2個程序就能各司其職:父程序繼續監聽,子程序完成連線操作。
connfd=accept(sockfd,...,...);
if (fork()==0)
close(connfd);//父程序
7。我們可以通過getsockname函式來獲得套介面的本地ip資訊,通過getpeername函式來獲得連線另外一端的ip資訊。
#include
int getsockname (int sockfd, struct sockaddr *addr, socklen_t *len);
得到套介面關聯的本地位址結構
int getpeername (int sockfd, struct sockaddr *addr, socklen_t *len);
得到遠端協議位址結構 len為struct sockaddr的長度
當中的sockfd必須是已連線套介面,不能是監聽套介面。
8.int close (int sockfd);
close只是減少某個套介面的計數,只有當計數為0時,核心才會向對方主機傳送fin。。。
如果確實需要傳送fin,那可以使用shutdown函式
int shutdown(int sockfd, int flags);
flags為shut_wr, shut_rd, shut_rdwr..關閉套介面的相應功能,(讀,寫),並傳送fin,不管計數是否為0。
程式設計,還是程式設計
喜歡程式設計,雖然水平一般,但還是執著地學習與程式設計有關的知識。中間因為工作關係與程式設計遠離了一段時間,現在又重拾起來,細想起來還是因為喜歡吧。喜歡程式軟體的思想和原理,喜歡程式 的魅力和成就感。程式設計軟體的思想是最值得學習的,一直認為思想決定行動,思想改變世界。每種軟體的流行和受人追捧,無不...
少兒程式設計程式設計
機械人比賽,聽上去讓人有一種高大上的科技感,沒錯,在大多數人眼裡,玩機械人那是科學家做的事情,不過隨著機械人教育的普及,越來越多的孩子也能夠駕馭這高大上的機械人。格物斯坦小坦克告訴你原因,這是歸結於孩子對於程式設計課程的學習,學會對機械人進行程式設計了,自然就能玩轉機械人啦。參加機械人比賽的意義遠遠...
LINUX程式設計 socket程式設計
什麼是套接字 套接字是一種通訊過程,它使客戶 伺服器系統的開發工作既可以在本地單機上進行,也可以跨網路進行。套接字建立過程 1,建立乙個套接字,這是分配給該伺服器程序的乙個作業系統資源,套接字由伺服器通過系統呼叫socket建立出來的,所以其它程序將不能對它進行訪問。2,給套接字起個名字,用系統呼叫...