C語言編程-socket基礎_第1頁
C語言編程-socket基礎_第2頁
C語言編程-socket基礎_第3頁
C語言編程-socket基礎_第4頁
C語言編程-socket基礎_第5頁
免費預覽已結束,剩余3頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

C語言編程-socket基礎C語言編程-socket基礎C語言編程-socket基礎V:1.0精細整理,僅供參考C語言編程-socket基礎日期:20xx年X月C語言編程---socket基礎2008-07-1610:22文章來源:先說套接字,網絡編程必不可少的東西.先看下面吧,這可是經典哦!最初socket是為支持TCP/IP協議而開發(fā)的,現在它已被認為是開發(fā)非RPCWindows網絡應用程序的最好途徑。socket作為BDSUNIX的進程通信機制,是進行程序間通訊(IPC)的BSD方法,這意味著socket用來讓一個進程和其他的進程互通信息。所謂socket通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過"套接字"向網絡發(fā)出請求或者應答網絡請求。開發(fā)原理:服務器,使用ServerSocket監(jiān)聽指定的端口,端口可以隨意指定(由于1024以下的端口通常屬于保留端口,在一些操作系統(tǒng)中不可以隨意使用,所以建議使用大于1024的端口),等待客戶連接請求,客戶連接后,會話產生;在完成會話后,關閉連接。客戶端,使用Socket對網絡上某一個服務器的某一個端口發(fā)出連接請求,一旦連接成功,打開會話;會話完成后,關閉Socket??蛻舳瞬恍枰付ù蜷_的端口,通常臨時的、動態(tài)的分配一個1024以上的端口。--winAPIsocket本文所談到的Socket函數如果沒有特別說明,都是指的WindowsSocketAPI。一、WSAStartup函數intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);使用Socket的程序在使用Socket之前必須調用WSAStartup函數。該函數的第一個參數指明程序請求使用的Socket版本,其中高位字節(jié)指明副版本、低位字節(jié)指明主版本;操作系統(tǒng)利用第二個參數返回請求的Socket的版本信息。當一個應用程序調用WSAStartup函數時,操作系統(tǒng)根據請求的Socket版本來搜索相應的Socket庫,然后綁定找到的Socket庫到該應用程序中。以后應用程序就可以調用所請求的Socket庫中的其它Socket函數了。該函數執(zhí)行成功后返回0。例:假如一個程序要使用版本的Socket,那么程序代碼如下wVersionRequested=MAKEWORD(2,1);err=WSAStartup(wVersionRequested,&wsaData);二、WSACleanup函數intWSACleanup(void);應用程序在完成對請求的Socket庫的使用后,要調用WSACleanup函數來解除與Socket庫的綁定并且釋放Socket庫所占用的系統(tǒng)資源。三、socket函數SOCKETsocket(intaf,inttype,intprotocol);應用程序調用socket函數來創(chuàng)建一個能夠進行網絡通信的套接字。第一個參數指定應用程序使用的通信協議的協議族,對于TCP/IP協議族,該參數置PF_INET;第二個參數指定要創(chuàng)建的套接字類型,流套接字類型為SOCK_STREAM、數據報套接字類型為SOCK_DGRAM;第三個參數指定應用程序所使用的通信協議。該函數如果調用成功就返回新創(chuàng)建的套接字的描述符,如果失敗就返回INVALID_SOCKET。套接字描述符是一個整數類型的值。每個進程的進程空間里都有一個套接字描述符表,該表中存放著套接字描述符和套接字數據結構的對應關系。該表中有一個字段存放新創(chuàng)建的套接字的描述符,另一個字段存放套接字數據結構的地址,因此根據是套接字數據結構都是在操作系統(tǒng)的內核緩沖里。下面是一個創(chuàng)建流套接字的例子:structprotoent*ppe;ppe=getprotobyname("tcp");SOCKETListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);四、closesocket函數intclosesocket(SOCKETs);closesocket函數用來關閉一個描述符為s套接字。由于每個進程中都有一個套接字描述符表,表中的每個套接字描述符都對應了一個位于操作系統(tǒng)緩沖區(qū)中的套接字數據結構,因此有可能有幾個套接字描述符指向同一個套接字數據結構。套接字數據結構中專門有一個字段存放該結構的被引用次數,即有多少個套接字描述符指向該結構。當調用closesocket函數時,操作系統(tǒng)先檢查套接字數據結構中的該字段的值,如果為1,就表明只有一個套接字描述符指向它,因此操作系統(tǒng)就先把s在套接字描述符表中對應的那條表項清除,并且釋放s對應的套接字數據結構;如果該字段大于1,那么操作系統(tǒng)僅僅清除s在套接字描述符表中的對應表項,并且把s對應的套接字數據結構的引用次數減1。closesocket函數如果執(zhí)行成功就返回0,否則返回SOCKET_ERROR。五、send函數intsend(SOCKETs,constcharFAR*buf,intlen,intflags);不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發(fā)送數據??蛻舫绦蛞话阌胹end函數向服務器發(fā)送請求,而服務器則通常用send函數來向客戶程序發(fā)送應答。該函數的第一個參數指定發(fā)送端套接字描述符;第二個參數指明一個存放應用程序要發(fā)送數據的緩沖區(qū);第三個參數指明實際要發(fā)送的數據的字節(jié)數;第四個參數一般置0。這里只描述同步Socket的send函數的執(zhí)行流程。當調用該函數時,send先比較待發(fā)送數據的長度len和套接字s的發(fā)送緩沖區(qū)的長度,如果len大于s的發(fā)送緩沖區(qū)的長度,該函數返回SOCKET_ERROR;如果len小于或者等于s的發(fā)送緩沖區(qū)的長度,那么send先檢查協議是否正在發(fā)送s的發(fā)送緩沖中的數據,如果是就等待協議把數據發(fā)送完,如果協議還沒有開始發(fā)送s的發(fā)送緩沖中的數據或者s的發(fā)送緩沖中沒有數據,那么send就比較s的發(fā)送緩沖區(qū)的剩余空間和len,如果len大于剩余空間大小send就一直等待協議把s的發(fā)送緩沖中的數據發(fā)送完,如果len小于剩余空間大小send就僅僅把buf中的數據copy到剩余空間里(注意并不是send把s的發(fā)送緩沖中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發(fā)送緩沖區(qū)的剩余空間里)。如果send函數copy數據成功,就返回實際copy的字節(jié)數,如果send在copy數據時出現錯誤,那么send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那么send函數也返回SOCKET_ERROR。要注意send函數把buf中的數據成功copy到s的發(fā)送緩沖的剩余空間里后它就返回了,但是此時這些數據并不一定馬上被傳到連接的另一端。如果協議在后續(xù)的傳送過程中出現網絡錯誤的話,那么下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執(zhí)行的最開始總要先等待套接字的發(fā)送緩沖中的數據被協議傳送完畢才能繼續(xù),如果在等待時出現網絡錯誤,那么該Socket函數就返回SOCKET_ERROR)注意:在Unix系統(tǒng)下,如果send在等待協議傳送數據時網絡斷開的話,調用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。六、recv函數intrecv(SOCKETs,charFAR*buf,intlen,intflags);不論是客戶還是服務器應用程序都用recv函數從TCP連接的另一端接收數據。該函數的第一個參數指定接收端套接字描述符;第二個參數指明一個緩沖區(qū),該緩沖區(qū)用來存放recv函數接收到的數據;第三個參數指明buf的長度;第四個參數一般置0。這里只描述同步Socket的recv函數的執(zhí)行流程。當應用程序調用recv函數時,recv先等待s的發(fā)送緩沖中的數據被協議傳送完畢,如果協議在傳送s的發(fā)送緩沖中的數據時出現網絡錯誤,那么recv函數返回SOCKET_ERROR,如果s的發(fā)送緩沖中沒有數據或者數據被協議成功發(fā)送完畢后,recv先檢查套接字s的接收緩沖區(qū),如果s接收緩沖區(qū)中沒有數據或者協議正在接收數據,那么recv就一直等待,只到協議把數據接收完畢。當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據copy到buf中(注意協議接收到的數據可能大于buf的長度,所以在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據copy完。recv函數僅僅是copy數據,真正的接收數據是協議來完成的),recv函數返回其實際copy的字節(jié)數。如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網絡中斷了,那么它返回0。注意:在Unix系統(tǒng)下,如果recv函數在等待協議接收數據時網絡斷開了,那么調用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。七、bind函數intbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);當創(chuàng)建了一個Socket以后,套接字數據結構中有一個默認的IP地址和默認的端口號。一個服務程序必須調用bind函數來給其綁定一個IP地址和一個特定的端口號??蛻舫绦蛞话悴槐卣{用bind函數來為其Socket綁定IP地址和斷口號。該函數的第一個參數指定待綁定的Socket描述符;第二個參數指定一個sockaddr結構,該結構是這樣定義的:structsockaddr{u_shortsa_family;charsa_data[14];};sa_family指定地址族,對于TCP/IP協議族的套接字,給其置AF_INET。當對TCP/IP協議族的套接字進行綁定時,我們通常使用另一個地址結構:structsockaddr_in{shortsin_family;u_shortsin_port;structin_addrsin_addr;charsin_zero[8];};其中sin_family置AF_INET;sin_port指明端口號;sin_addr結構體中只有一個唯一的字段s_addr,表示IP地址,該字段是一個整數,一般用函數inet_addr()把字符串形式的IP地址轉換成unsignedlong型的整數值后再置給s_addr。有的服務器是多宿主機,至少有兩個網卡,那么運行在這樣的服務器上的服務程序在為其Socket綁定IP地址時可以把htonl(INADDR_ANY)置給s_addr,這樣做的好處是不論哪個網段上的客戶程序都能與該服務程序通信;如果只給運行在多宿主機上的服務程序的Socket綁定一個固定的IP地址,那么就只有與該IP地址處于同一個網段上的客戶程序才能與該服務程序通信。我們用0來填充sin_zero數組,目的是讓sockaddr_in結構的大小與sockaddr結構的大小一致。下面是一個bind函數調用的例子:structsockaddr_insaddr;=AF_INET;=htons(8888);=htonl(INADDR_ANY);bind(ListenSocket,(structsockaddr*)&saddr,sizeof(saddr));八、listen函數intlisten(SOCKETs,intbacklog);服務程序可以調用listen函數使其流套接字s處于監(jiān)聽狀態(tài)。處于監(jiān)聽狀態(tài)的流套接字s將維護一個客戶連接請求隊列,該隊列最多容納backlog個客戶連接請求。假如該函數執(zhí)行成功,則返回0;如果執(zhí)行失敗,則返回SOCKET_ERROR。九、accept函數SOCKETaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);服務程序調用accept函數從處于監(jiān)聽狀態(tài)的流套接字s的客戶連接請求隊列中取出排在最前的一個客戶請求,并且創(chuàng)建一個新的套接字來與客戶套接字創(chuàng)建連接通道,如果連接成功,就返回新創(chuàng)建的套接字的描述符,以后與客戶套接字交換數據的是新創(chuàng)建的套接字;如果失敗就返回INVALID_SOCKET。該函數的第一個參數指定處于監(jiān)聽狀態(tài)的流套接字;操作系統(tǒng)利用第二個參數來返回新創(chuàng)建的套接字的地址結構;操作系統(tǒng)利用第三個參數來返回新創(chuàng)建的套接字的地址結構的長度。下面是一個調用accept的例子:structsockaddr_inServerSocketAddr;intaddrlen;addrlen=sizeof(ServerSocketAddr);ServerSocket=accept(ListenSocket,(structsockaddr*)&ServerSocketAddr,&addrlen);十、connect函數intconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);客戶程序調用connect函數來使客戶Sockets與監(jiān)聽于name所指定的計算機的特定端口上的服務Socket進行連接。如果連接成功,connect返回0;如果失敗則返回SOCKET_ERROR。下面是一個例子:structsockaddr_indaddr;memset((void*)&daddr,0,sizeof(daddr));=AF_INET;=htons(8888);"");connect(ClientSocket,(structsockaddr*)&daddr,sizeof(daddr));下面是兩個例子,一個服務端一個客戶端.先打開服務端等待連接,客戶端運行后,可以向服務端發(fā)送字符串.不多說了,看源碼吧!#include<>#pragmacomment(lib,"ws2_32")#include<>intmain(intargc,char*[]){n",inet_ntoa);while(true){intret=recv(sClient,revData,255,0);if(ret==0||(ret==SOCKET_ERROR&&WSAGetLastError()==WSAECONNRESET)){printf("%s關閉連接\n",inet_ntoa);closesocket(sClient);break;}else{revData[ret]='\0';printf("%s",revData);}}}closesocket(sServer);WSACleanup();return0;}#include<>#pragmacomment(lib,"ws2_32")#include<>#definePORT1129#defineADDRESS""intmain(){//加載winsock庫WSADATAwsaData;WORD

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論