C語言 socket 編程學習

對于SOCKET在這里我不想究其歷史,我只想說其時它是一種進程通訊的方式,簡言之就是調用這個網絡庫的一些API函數就能實現分布在不同主機的相關進程之間的數據交換.
??? SOCKET中首先我們要理解如下幾個定義概念:
??? 一是IP地址:IP Address我想很容易理解,就是依照TCP/IP協議分配給本地主機的網絡地址,就向兩個進程要通訊,任一進程要知道通訊對方的位置,位置如何來確定,就用對方的IP
??? 二是端口號:用來標識本地通訊進程,方便OS提交數據.就是說進程指定了對方進程的網絡IP,但這個IP只是用來標識進程所在的主機,如何來找到運行在這個主機的這個進程呢,就用端口號.
??? 三是連接:指兩個進程間的通訊鏈路.
??? 四是半相關:網絡中用一個三元組可以在全局唯一標志一個進程:

??? (協議,本地地址,本地端口號)

??? 這樣一個三元組,叫做一個半相關,它指定連接的每半部分。


??? 五是全相關

??? 一個完整的網間進程通信需要由兩個進程組成,并且只能使用同一種高層協議。也就是說,不可能通信的一端用TCP協議,而另一端用UDP協議。因此一個完整的網間通信需要一個五元組來標識:

??? (協議,本地地址,本地端口號,遠地地址,遠地端口號)

??? 這樣一個五元組,叫做一個相關(association),即兩個協議相同的半相關才能組合成一個合適的相關,或完全指定組成一連接。
??? 客戶/服務器模式
??? 在TCP/IP網絡應用中,通信的兩個進程間相互作用的主要模式是客戶/服務器模式(Client/Server model),即客戶向服務器發出服務請求,服務器接收到請求后,提供相應的服務。客戶/服務器模式的建立基于以下兩點:首先,建立網絡的起因是網絡中軟硬件資源、運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。其次,網間進程通信完全是異步的,相互通信的進程間既不存在父子關系,又不共享內存緩沖區,因此需要一種機制為希望通信的進程間建立聯系,為二者的數據交換提供同步,這就是基涌紀紀戶/服務器模式的TCP/IP。

??? 客戶/服務器模式鑰紀紀作過程中采取的是主動請求方式:

??? 首先服務器方要先啟動,并根據請求提供相應服務:

??? 1. 打開一通信通道并告知本地主機,它愿意在某一公認地址上(周知口,如FTP為21)接收客戶請求;

??? 2. 等待客戶請求到達該端口;

??? 3. 接收到重復服務請求,處理該請求并發送應答信號。接收到并發服務請求,要激活一新進程來處理這個客戶請求(如UNIX系統中用fork、exec)。新進程處理此客戶請求,并不需要對其它請求作出應答。服務完成后,關閉此新進程與客戶的通信鏈路,并終止。

??? 4. 返回第二步,等待另一客戶請求。

??? 5. 關閉服務器


??? 客戶方:

??? 1. 打開一通信通道,并連接到服務器所在主機的特定端口;

??? 2. 向服務器發服務請求報文,等待并接收應答;繼續提出請求……

??? 3. 請求結束后關閉通信通道并終止。


??? 從上面所描述過程可知:

??? 1. 客戶與服務器進程的作用是非對稱的,因此編碼不同。

??? 2. 服務進程一般是先涌紀紀戶請求而啟動的。只要系統運行,該服務進程一直存在,直到正常或強迫終止。


??? 介紹完基礎知識,下面就介紹一些API函數:
??? 創建套接字──socket()
??? 應用程序在使用套接字前,首先必須擁有一個套接字,系統調用socket()向應用程序提供創建套接字的手段,其調用格式如下:

??? SOCKET PASCAL FAR socket(int af, int type, int protocol);

??? 該調用要接收三個參數:af、type、protocol。參數af指定通信發生的區域,:AF_UNIX、AF_INET、AF_NS等,而DOS、 WINDOWS中僅支持AF_INET,它是網際網區域。因此,地址族與協議族相同。參數type 描述要建立的套接字的類型。這里分三種:一是TCP流式套接字(SOCK_STREAM)提供了一個面向連接、可靠的數據傳輸服務,數據無差錯、無重復地發送,且按發送順序接收。內設流量控制,避免數據流超限;數據被看作是字節流,無長度限制。文件傳送協議(FTP)即使用流式套接字。
??? 二是數據報式套接字(SOCK_DGRAM)提供了一個無連接服務。數據包以獨立包形式被發送,不提供無錯保證,數據可能丟失或重復,并且接收順序混亂。網絡文件系統(NFS)使用數據報式套接字。三是原始式套接字 (SOCK_RAW)該接口允許對較低層協議,如IP、ICMP直接訪問。常用于檢驗新的協議實現或訪問現有服務中配置的新設備.參數protocol說明該套接字使用的特定協議,如果調用者不希望特別指定使用的協議,則置為0,使用默認的連接模式。根據這三個參數建立一個套接字,并將相應的資源分配給它,同時返回一個整型套接字號。因此,socket()系統調用實際上指定了相關五元組中的“協議”這一元。
??? 指定本地地址──bind()
??? 當一個套接字用socket()創建后,存在一個名字空間(地址族),但它沒有被命名。bind()將套接字地址(包括本地主機地址和本地端口地址)與所創建的套接字號聯系起來,即將名字賦予套接字,以指定本地半相關。其調用格式如下:

??? int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);

?

參數s是由socket()調用返回的并且未作連接的套接字描述符(套接字號)。參數name 是賦給套接字s的本地地址(名字),其長度可變,結構隨通信域的不同而不同。namelen表明了name的長度.如果沒有錯誤發生,bind()返回0。否則返回SOCKET_ERROR。
??? 建立套接字連接──connect()與accept()
??? 這兩個系統調用用于完成一個完整相關的建立,其中connect()用于建立連接。無連接的套接字進程也可以調用connect(),但這時在進程之間沒有實際的報文交換,調用將從本地操作系統直接返回。這樣做的優點是程序員不必為每一數據指定目的地址,而且如果收到的一個數據報,其目的端口未與任何套接字建立“連接”,便能判斷該端靠紀紀可操作。而accept()用于使服務器等待來自某客戶進程的實際連接。

??? connect()的調用格式如下:

??? int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

??? 參數s是欲建立連接的本地套接字描述符。參數name指出說明對方套接字地址結構的指針。對方套接字地址長度由namelen說明。

??? 如果沒有錯誤發生,connect()返回0。否則返回值SOCKET_ERROR。在面向連接的協議中,該調用導致本地系統和外部系統之間連接實際建立。

??? 由于地址族總被包含在套接字地址結構的前兩個字節中,并通過socket()調用與某個協議族相關。因此bind()和connect()無須協議作為參數。

??? accept()的調用格式如下:

??? SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

??? 參數s為本地套接字描述符,在用做accept()調用的參數前應該先調用過listen()。addr 指向客戶方套接字地址結構的指針,用來接收連接實體的地址。addr的確切格式由套接字創建時建立的地址族決定。addrlen 為客戶方套接字地址的長度(字節數)。如果沒有錯誤發生,accept()返回一個SOCKET類型的值,表示接收到的套接字的描述符。否則返回值INVALID_SOCKET。

??? accept() 用于面向連接服務器。參數addr和addrlen存放客戶方的地址信息。調用前,參數addr 指向一個初始值為空的地址結構,而addrlen 的初始值為0;調用accept()后,服務器等待從編號為s的套接字上接受客戶連接請求,而連接請求是由客戶方的connect()調用發出的。當有連接請求到達時,accept()調用將請求連接隊列上的第一個客戶方套接字地址及長度放入addr 和addrlen,并創建一個與s有相同特性的新套接字號。新的套接字可用于處理服務器并發請求。

?

??? 四個套接字系統調用,socket()、bind()、 connect()、accept(),可以完成一個完全五元相關的建立。socket()指定五元組中的協議元,它的用法與是否為客戶或服務器、是否面向連接無關。bind()指定五元組中的本地二元,即本地主機地址和端口號,其用法與是否面向連接有關:在服務器方,無論是否面向連接,均要調用 bind(),若采用面向連接,則可以不調用bind(),而通過connect()自動完成。若采用無連接,客戶方必須使用bind()以獲得一個唯一的地址。
??? 監聽連接──listen()
??? 此調用用于面向連接服務器,表明它愿意接收連接。listen()需在accept()之前調用,其調用格式如下:

??? int PASCAL FAR listen(SOCKET s, int backlog);

??? 參數s標識一個本地已建立、尚未連接的套接字號,服務器愿意從它上面接收請求。backlog表示請求連接隊列的最大長度,用于限制排隊請求的個數,目前允許的最大值為5。如果沒有錯誤發生,listen()返回0。否則它返回SOCKET_ERROR。

??? listen()在執行調用過程中可為沒有調用過bind()的套接字s完成所必須的連接,并建立長度為backlog的請求連接隊列。

??? 調用listen()是服務器接收一個連接請求的四個步驟中的第三步。它在調用socket()分配一個流套接字,且調用bind()給s賦于一個名字之后調用,而且一定要在accept()之前調用。
??? 數據傳輸──send()與recv()
??? 當一個連接建立以后,就可以傳輸數據了。常用的系統調用有send()和recv()。

??? send()調用用于鑰紀紀數s指定的已連接的數據報或流套接字上發送輸出數據,格式如下:

??? int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);

??? 參數s為已連接的本地套接字描述符。buf 指向存有發送數據的緩沖區的指針,其長度由len 指定。flags 指定傳輸控制方式,如是否發送帶外數據等。如果沒有錯誤發生,send()返回總共發送的字節數。否則它返回SOCKET_ERROR。
??? recv()調用用于s指定的已連接的數據報或流套接字上接收輸入數據,格式如下:

??? int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);

??? 參數s 為已連接的套接字描述符。buf指向接收輸入數據緩沖區的指針,其長度由len 指定。flags 指定傳輸控制方式,如是否接收帶外數據等。如果沒有錯誤發生,recv()返回總共接收的字節數。如果連接被關閉,返回0。否則它返回SOCKET_ERROR。
??? 輸入/輸出多路復用──select()
??? select() 調用用來檢測一個或多個套接字的狀態。對每一個套接字來說,這個調用可以請求讀、寫或錯誤狀態方面的信息。請求給定狀態的套接字集合由一個fd_set結構指示。在返回時,此結構被更新,以反映那些滿足特定條件的套接字的子集,同時, select()調用返回滿足條件的套接字的數目,其調用格式如下:

??? int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

??? 參數nfds指明被檢查的套接字描述符的值域,此變量一般被忽略。

??? 參數readfds指向要做讀檢測的套接字描述符集合的指針,調用者希望從中讀取數據。參數writefds 指向要做寫檢測的套接字描述符集合的指針。 exceptfds指向要檢測是否出錯的套接字描述符集合的指針。timeout指向select()函數等待的最大時間,如果設為NULL則為阻塞操作。select()返回包含在fd_set結構中已準備好的套接字描述符的總數目,或者是發生錯誤則返回SOCKET_ERROR。
??? 關閉套接字──closesocket()
??? closesocket()關閉套接字s,并釋放分配給該套接字的資源;如果s涉及一個打開的TCP連接,則該連接被釋放。closesocket()的調用格式如下:

??? BOOL PASCAL FAR closesocket(SOCKET s);

??? 參數s待關閉的套接字描述符。如果沒有錯誤發生,closesocket()返回0。否則返回值SOCKET_ERROR。

??? 以上就是SOCKET API一些常用的API函數,下面我在介紹C/S模式就是客戶機/服務器通訊模式,服務器啟動服務并在相應端口內偵聽,客戶機打開連接,完成通訊鏈路的建立后,雙方進行數據交互,完畢后關閉套接字


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450673.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450673.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450673.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

dependency 中的 classifier屬性

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 classifier元素用來幫助定義構件輸出的一些附屬構件。附屬構件與主構件對應,比如主構件是 kimi-app-2.0.0.jar 該項目可能還…

PHP超全局變量$_SERVER

$_SERVER 是一個包含了諸如頭信息(header)、路徑(path)、以及腳本位置(script locations)等等信息的數組。這個數組中的項目由 Web 服務器創建。不能保證每個服務器都提供全部項目;服務器可能會忽略一些,或者提供一些沒有在這里列舉出來的項目。 $_SERVE…

VC讀寫XML文件

1、安裝MSXML 4.0 SP2。在VC6中建立一個基于Dialog的工程。如圖: 在界面上放置3個編輯框、1個按鈕控件。其中屬性設置如下。 編輯框: IDCategoryVariable TypeVariable NameIDC_IDValueCStringm_strIdIDC_AUTHORValueCStringm_strAuthorIDC_TITLEValueCS…

XCode10 swift4.2 適配遇到的坑

以下是2018年10月23日更新 經過大約一個月的時間的適配,項目正式使用XCode10(以下簡稱為10 or XC10)大部分庫都升級為Swift4.2(以下簡稱為 4.2 or S4.2),下面是適配過程中遇到的一些坑。 1. Swift4、Swift4.2混編 如果你對項目是小…

學生管理系統Java版

簡單的學生管理系統 主界面編寫: 1.用輸出語句完成主界面的編寫 2.用Scanner語句實現鍵盤的錄入 3.用swich語句完成操作的選擇 4.用循環完成再次回到主界面 代碼實現: while (true) {//1.用輸出語句完成主界面的編寫System.out.println("--------…

dubbo 配置文件詳解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、dubbo常用配置 <dubbo:service/> 服務配置&#xff0c;用于暴露一個服務&#xff0c;定義服務的元信息&#xff0c;一個服務可…

ASP.NET Core 實戰:Linux 小白的 .NET Core 部署之路

一、前言 最近一段時間自己主要的學習計劃還是按照畢業后設定的計劃&#xff0c;自己一步步的搭建一個前后端分離的 ASP.NET Core 項目&#xff0c;目前也還在繼續學習 Vue 中&#xff0c;雖然中間斷了很長時間&#xff0c;好歹還是堅持下來了&#xff0c;嗯&#xff0c;看了看…

學以致用十三-----Centos7.2+python3+YouCompleteMe成功歷程

歷經幾天的摸索&#xff0c;趟過幾趟坑之后&#xff0c;終于完成YouCompleteMe的安裝配置。 今天同樣是個不能忘記的日子&#xff0c;國恥日&#xff0c;勿忘國恥。&#xff08;9.18&#xff09; 服務器安裝好&#xff0c;基本配置配置好后&#xff0c;開始安裝。 一、檢查服務…

VC畫圖用到的主要方法

1。鼠標落下&#xff0c;記錄鼠標的起始位置 void CMyEasyDrawView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 //graph->m_nTypedlg-> m_bStartDraw true; m_PtPress m_PtLast point; CView::OnLButtonDown…

【最新版】Java學習路線(含B站口碑推薦視頻鏈接)

文章目錄關于如何自學一、計算機網絡二、數據結構與算法三、操作系統四、計算機組成原理五、編譯原理六、設計模式七、MySQL八、實操工具九、JAVA并發與JVM十、Redis十一、Linux十二、Java路線學習尚硅谷黑馬程序員動力節點狂神說十三、Java基礎十四、JavaWeb十五、框架十六、微…

記錄no static method cannot be reference

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; no static method cannot be reference 我一直以為是在靜態方法中調用了非靜態方法&#xff0c;實際上只是我在注…

文件存儲權限

Android 6.0及以上&#xff0c;需要動態申請權限&#xff1a; Manifest.permission.READ_EXTERNAL_STORAGE Manifest.permission.WRITE_EXTERNAL_STORAGE <uses-permission-sdk-23 android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permis…

從工具的奴隸到工具的主人

摘要&#xff1a;我們每個人都是工具的奴隸。隨著我們的學習&#xff0c;我們不斷的加深自己對工具的認識&#xff0c;從而從它們里面解脫出來。現在我就來說一下我作為各種工具的奴隸&#xff0c;以及逐漸擺脫它們的思想控制的歷史吧。 當我高中畢業進入大學計算機系的時候&am…

記錄A component required a bean named ‘studentService‘ that could not be found.

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; A component required a bean named studentService that could not be found. 出問題的代碼行&#xff1a; &l…

Java---利用程序實現在控制臺聊天

一.普通版&#xff08;不能實現隨意輸入&#xff09; 電腦A(服務器端) package day; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner;public class Mysever {public static void…

16.看板方法——三類改進機會筆記

00.三種常見的模型和它們一些變種&#xff1a;約束理論及其主要理念&#xff1b;還有聚焦于分析和減少變異性的模型及其變種等。 01.五步聚焦法 *a.識別約束 *b.作出決定&#xff0c;以最大化利用約束 *c.使系統中的其余一切部分都服從于b中做出決定 *d.突破約束 *e.避免惰性&a…

C/C++的64位整型

在C/C中&#xff0c;64為整型一直是一種沒有確定規范的數據類型。現今主流的編譯器中&#xff0c;對64為整型的支持也是標準不一&#xff0c;形態各異。一般來說&#xff0c;64位整型的定義方式有long long和__int64兩種(VC還支持_int64)&#xff0c;而輸出到標準輸出方式有pri…

記錄 Duplicate spring bean id dubbo

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 啟動工程 報錯如題&#xff1a; Duplicate spring bean id dubbo &#xff0c;意思是id 重復。 原因是我在加載配置文件時加載了兩個…

1.KafKa-介紹

轉載于:https://www.cnblogs.com/v-lcc/p/9674975.html

關于日志的123

寫在前面&#xff1a; 關于日志其實有很多想說的&#xff0c;不過將自己整理的文檔轉化為Blog還是比較花時間的&#xff0c;偶有疏漏&#xff0c;請多包涵。 本篇文章所講均只止于Java。 日志的作用&#xff1a; 1.定位問題&#xff0c;對于一個系統而言&#xff0c;總是會有些…