九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Socket網(wǎng)絡(luò)編程指導(dǎo)

Socket網(wǎng)絡(luò)編程指導(dǎo)

2011-3-19

1/37

guoxiaol@mail.ustc.edu.cn

什么是Socket

2011-3-19

2/37

BSD Socket(伯克立套接字)是通過(guò)標(biāo)準(zhǔn)的UNIX文件描述符和其它程序通訊的一個(gè)方法,目前已經(jīng)被廣泛移植到各個(gè)平臺(tái)。

 

Socket是獨(dú)立于具體協(xié)議的網(wǎng)絡(luò)編程接口。在ISO模型中,主要位于會(huì)話層和傳輸層。

Socket的類型

2011-3-19

3/37

流式套接字(SOCK_STREAM)
    
提供了一個(gè)面向連接,可靠的數(shù)據(jù)傳輸服務(wù),數(shù)據(jù)無(wú)差錯(cuò),無(wú)重復(fù)的發(fā)送且按發(fā)送順序接收。內(nèi)設(shè)流量控制,避免數(shù)據(jù)流超限;數(shù)據(jù)被看作是字節(jié)流,無(wú)長(zhǎng)度限制。

 

數(shù)據(jù)報(bào)式套接字(SOCK_DGRAM)
    
提供了一個(gè)無(wú)連接服務(wù)。數(shù)據(jù)包以獨(dú)立包形式被發(fā)送,不提供無(wú)差錯(cuò)保證,數(shù)據(jù)可能丟失或重復(fù),并且接收順序無(wú)序。

 

原始式套接字(SOCK_RAW)
    
該接口允許對(duì)較低層次協(xié)議,如IP、ICMP直接訪問(wèn)。

2011-3-19

4/37

Socket所在層次示意圖

Application program

Stream

Socket

Interface

TCP

UDP

Datagram

Socket

Interface

Raw

Socket

Interface

IP

Physical and data link layers

基本套接字調(diào)用

2011-3-19

5/37

創(chuàng)建套接字    socket();
綁定本機(jī)端口       bind();
建立連接              connect();

       接受連接              accept();
監(jiān)聽(tīng)端口              listen();
數(shù)據(jù)傳輸              send(), recv() ;
關(guān)閉套接字    close();

Socket相關(guān)的數(shù)據(jù)結(jié)構(gòu)

2011-3-19

6/37

struct sockaddr_in

   {
   short int   sin_family;      /* 通信類型 */
   unsigned short int   sin_port;  /* 端口號(hào),網(wǎng)絡(luò)字節(jié)順序*/
   struct in_addr  sin_addr;  /* Internet 地址,網(wǎng)絡(luò)字節(jié)順序*/
   unsigned char sin_zero[8];   /*沒(méi)用*/

    };

 

struct in_addr

    {

             in_addr_t    s_addr;  /* 存儲(chǔ)32bit IP地址*/

    }

網(wǎng)絡(luò)字節(jié)順序和主機(jī)字節(jié)順序

2011-3-19

7/37

Big-Endian Byte Order:字節(jié)的高位在內(nèi)存中放在存儲(chǔ)單元的起始位置

00001010

00010111

00001110

00000110

00001010

00010111

00001110

00000110

Memory

Little-Endian Byte Order : Big-Endian相反

A

A+1

A+2

A+3

2011-3-19

8/40

Host byte order Little-Endian

16-bit

32-bit

Network byte orderBig-Endian

16-bit

32-bit

htons()

ntohs()

htonl()

ntohl()

網(wǎng)絡(luò)字節(jié)順序和主機(jī)字節(jié)順序的轉(zhuǎn)換

IP地址的轉(zhuǎn)換

2011-3-19

9/37

int inet_aton(const char* strptr, struct in_addr                       *addrptr);

   從點(diǎn)狀十進(jìn)制到322進(jìn)制的轉(zhuǎn)換,如“202.38.64.185

   11001010,0010011001000000,10111001

char  *inet_ntoa(struct in_addr inadd);

   inet_aton()的功能相反

相關(guān)的內(nèi)存操作函數(shù)

2011-3-19

10/37

void *memset(void *buffer, int c, int count);

    buffer所指內(nèi)存區(qū)域的前count個(gè)字節(jié)設(shè)置成字符c。

void *memcpy(void *dest, void *src, unsigned int                                    count);

   src所指內(nèi)存區(qū)域復(fù)制count個(gè)字節(jié)到dest所指內(nèi)存區(qū)域。

Void bzero(void *s, int n );

    置字節(jié)字符串s的前n個(gè)字節(jié)為零。

域名和IP地址的轉(zhuǎn)換

2011-3-19

11/37

struct hostent *gethostbyname(const char *name);

struct hostent

{
 char    *h_name; /* 主機(jī)的官方域名 */
 char  **h_aliases; /* 一個(gè)以NULL結(jié)尾的主機(jī)別名數(shù)組 */
 int  h_addrtype; /* 返回的地址類型,在Internet環(huán)境下為AF-                                 INET */
 int  h_length; /* 地址的字節(jié)長(zhǎng)度 */
 char  **h_addr_list; /* 一個(gè)以0結(jié)尾的數(shù)組,包含該主機(jī)的所有地                     */
};
#define h_addr h_addr_list[0]  /*
h-addr-list中的第一個(gè)地址*/

建立Socket

2011-3-19

12/37

int socket(int domain, int type, int protocol);

參數(shù)說(shuō)明:

       domain:通信使用的協(xié)議族,即網(wǎng)絡(luò)的類型,對(duì)于             TCP/IP來(lái)說(shuō),是AF_INET

    type: SOCK_STREAM / SOCK_DGRAM

    protocol: 通常為0

 

 返回整形的socket描述符,如果出錯(cuò),返回-1

Socket的配置

2011-3-19

13/37

Socket描述符是一個(gè)指向內(nèi)部數(shù)據(jù)結(jié)構(gòu)的指針,它指向描述符表入口。調(diào)用Socket()函數(shù)時(shí),將建立一個(gè)Socket,為一個(gè)Socket數(shù)據(jù)結(jié)構(gòu)分配存儲(chǔ)空間。

兩個(gè)網(wǎng)絡(luò)程序之間的一個(gè)網(wǎng)絡(luò)連接包括五種信息:通信協(xié)議、本地主機(jī)地址和端口、遠(yuǎn)端主機(jī)地址和端口。

在使用socket進(jìn)行網(wǎng)絡(luò)傳輸以前,必須配置該socket。       面向連接的socket客戶端調(diào)用connect()函數(shù)在socket數(shù)據(jù)結(jié)構(gòu)中保存本地和遠(yuǎn)端信息。

              無(wú)連接socket的客戶端和服務(wù)端以及面向連接socket的服務(wù)端通過(guò)調(diào)用bind()函數(shù)來(lái)配置本地信息。

綁定Socket

2011-3-19

14/37

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

    sockfdsocket()返回的socket描述符;

    my_addr是指向包含本機(jī)IP地址及端口號(hào)等信息的                      sockaddr類型的指針;                                          addrlen一般被設(shè)置為sizeof(struct sockaddr_in)


成功被調(diào)用時(shí)返回0;出現(xiàn)錯(cuò)誤時(shí)返回"-1" 

綁定前sockaddr_in的初始化

2011-3-19

15/37

my_addr.sin_family = AF_INET;     //選擇網(wǎng)絡(luò)類型為TCP/IP

my_addr.sin_addr.s_addr = inet_addr(“210.45.64.222");

my_addr.sin_port = htons( 8888 );  //選擇端口8888

addr_len = sizeof(struct sockaddr_in);               

memset(&my_addr.sin_zero, ‘\0’, sizeof(my_addr.sin_zero));  

建立連接(客戶端)

2011-3-19

16/37

面向連接的客戶程序使用connect函數(shù)來(lái)配置socket并與遠(yuǎn)端服務(wù)器建立一個(gè)TCP連接,其函數(shù)原型為:
int connect( int sockfd, struct sockaddr_in                                 *serv_addr
,int addrlen);

serv_addr是包含遠(yuǎn)端主機(jī)IP地址和端口號(hào)的指針;addrlen是遠(yuǎn)端地址結(jié)構(gòu)的長(zhǎng)度

成功則返回0,出現(xiàn)錯(cuò)誤時(shí)返回-1

建立連接(服務(wù)器端)

2011-3-19

17/37

服務(wù)器監(jiān)聽(tīng)端口:listen函數(shù)使socket處于被動(dòng)的監(jiān)聽(tīng)模式,并為該socket建立一個(gè)輸入數(shù)據(jù)隊(duì)列,將到達(dá)的服務(wù)請(qǐng)求保存在此隊(duì)列中,直到程序處理它們。
int listen(int sockfd
int backlog);

backlog:請(qǐng)求連接隊(duì)列的最大長(zhǎng)度

成功返回0,出錯(cuò)返回-1

建立連接(服務(wù)器端)

2011-3-19

18/37

accept()函數(shù)讓服務(wù)器接收客戶的連接請(qǐng)求。在建立好輸入隊(duì)列后,服務(wù)器就調(diào)用accept函數(shù),然后睡眠并等待客戶的連接請(qǐng)求。
int accept(int sockfd, sockaddr_in *addr, int                   *addrlen);

addr是指向sockaddr_in變量的指針,該變量存放提出連接請(qǐng)求服務(wù)的主機(jī)的信息

返回新的socket描述符,和請(qǐng)求連接進(jìn)程的地址聯(lián)系起來(lái)在新的socket描述符上進(jìn)行數(shù)據(jù)傳輸操作。原來(lái)的socket繼續(xù)listen

數(shù)據(jù)傳輸(1)

2011-3-19

19/37

send()recv()這兩個(gè)函數(shù)用于面向連接的socket上進(jìn)行數(shù)據(jù)傳輸。
send()
函數(shù)原型為:
int send(int sockfd, const void *msg, int len, int                      flags);     
    sockfd
是用來(lái)傳輸數(shù)據(jù)的socket描述符;msg是指向要發(fā)送數(shù)據(jù)的指針;len是以字節(jié)為單位的數(shù)據(jù)長(zhǎng)度;flags一般置為0

send() 返回實(shí)際發(fā)送的字節(jié)數(shù),可能會(huì)少于希望發(fā)送的數(shù)據(jù)。在程序中應(yīng)該將send()的返回值與欲發(fā)送的字節(jié)數(shù)進(jìn)行比較。當(dāng)返回值與len不匹配時(shí),應(yīng)該進(jìn)行處理。

數(shù)據(jù)傳輸(2)

2011-3-19

20/37

recv()函數(shù)原型為:
int recv(int sockfd, void *buf, int len, unsigned int            flags);

buf 是存放接收數(shù)據(jù)的緩沖區(qū);len是緩沖區(qū)的長(zhǎng)度。flags也被置為0

recv()返回實(shí)際接收的字節(jié)數(shù),當(dāng)出現(xiàn)錯(cuò)誤時(shí),返回-1

數(shù)據(jù)傳輸(3)

2011-3-19

21/37

sendto()recvfrom()用于在無(wú)連接的數(shù)據(jù)報(bào)socket

    式下進(jìn)行數(shù)據(jù)傳輸。由于本地socket沒(méi)有與遠(yuǎn)端機(jī)器建立連接,所以在發(fā)送數(shù)據(jù)時(shí)要指明目的地址。
     

sendto()函數(shù)原型為:

    int sendto(int sockfd, const void *buf,int buflen,                 unsigned  int flags, const struct                             sockaddr_in *to,  int tolen); 

數(shù)據(jù)傳輸(4)

2011-3-19

22/37

recvfrom()函數(shù)原型為:
int recvfrom(int sockfd
void *buf,int buflen,                          unsigned int flagsstruct sockaddr_in                        *from,int  *fromlen);

 

recvfrom()函數(shù)返回接收到的字節(jié)數(shù),當(dāng)出錯(cuò)時(shí)返回-1

結(jié)束傳輸

2011-3-19

23/37

close()函數(shù)用于釋放socket,停止在該socket上的任何數(shù)據(jù)操作:     close(sockfd);
    

也可以調(diào)用shutdown() 來(lái)關(guān)閉該socket

       該函數(shù)允許只停止某個(gè)方向上的數(shù)據(jù)傳輸,而一個(gè)方向上的數(shù)據(jù)傳輸繼續(xù)進(jìn)行。
    int shutdown(int sockfd
,int how);
   
參數(shù) how允許為shutdown操作選擇以下幾種方式:
    0-------
不允許繼續(xù)接收數(shù)據(jù)
    1-------
不允許繼續(xù)發(fā)送數(shù)據(jù)
    2-------
不允許繼續(xù)發(fā)送和接收數(shù)據(jù),
    shutdown
在操作成功時(shí)返回0,出錯(cuò)時(shí)返回-1。

C/S結(jié)構(gòu)

2011-3-19

24/37

服務(wù)器端要先啟動(dòng),提供相應(yīng)服務(wù):

  1:打開(kāi)一通信通道并告知本地主機(jī),它愿意在某一個(gè)公認(rèn)地址上接收客戶請(qǐng)求。

  2:等待客戶請(qǐng)求到達(dá)該端口。

  3:接收到服務(wù)請(qǐng)求,處理該請(qǐng)求并發(fā)送應(yīng)答信號(hào)。

  4:返回第二步,等待另一客戶請(qǐng)求

  5:關(guān)閉服務(wù)器。

客戶端:

  1、打開(kāi)一通信通道,并連接到服務(wù)器所在主機(jī)的特定端口。

  2、向服務(wù)器發(fā)送服務(wù)請(qǐng)求報(bào)文,等待并接收應(yīng)答;繼續(xù)提出請(qǐng)求……

  3、請(qǐng)求結(jié)束后關(guān)閉通信通道并終止。

流程圖

2011-3-19

25/37

TCP服務(wù)器端

(循環(huán)服務(wù)器)

TCP客戶端

socket( )

bind( )

listen( )

accept( )

socket( )

send( )

connect( )

recv( )

recv( )

send( )

close( )

close( )

UDP服務(wù)器端

UDP客戶端

socket( )

bind( )

listen( )

recvfrom( )

sendto( )

socket( )

bind( )

close( )

close( )

簡(jiǎn)單的例子

2011-3-19

26/37

int sockfd, newsockfd,addr_len, sendnum;

struct sockaddr_in my_addr, their_addr;

char * msg = “welcome”;

sockfd = socket( AF_INET, SOCK_STREAM, 0 );  //建立socket

 

my_addr.sin_family = AF_INET;                           //選擇網(wǎng)絡(luò)類型為TCP/IP

my_addr.sin_addr.s_addr = inet_addr(“210.45.64.222");

my_addr.sin_port = htons( 8888 );                        //選擇端口8888

addr_len = sizeof( struct sockaddr_in);               

memset(&my_addr.sin_zero, ‘\0’, sizeof(my_addr.sin_zero));  

 

bind(sockfd, (struct sockaddr *)&my_addr, addr_len);   //綁定socket

 

listen(sockfd,10);         //監(jiān)聽(tīng),等待連接,等待連接隊(duì)列最大長(zhǎng)度為10

簡(jiǎn)單的例子(續(xù))

2011-3-19

27/37

While( 1 )

{

       newsockfd = accept( sockfd, (struct sockaddr *)&my_addr, addr_len);

      sendnum = send(newsockfd, msg, strlen(msg)+1, 0);

      ……

      close(newsockfd);

 }

 

 close(sockfd);

阻塞與非阻塞(1)

2011-3-19

28/37

阻塞函數(shù):指其完成指定的任務(wù)之前不允許程序調(diào)用另一個(gè)函數(shù),在Windows下還會(huì)阻塞本線程消息的發(fā)送。

    eg: recv( ) ,當(dāng)socket工作在阻塞模式的時(shí)候,如果沒(méi)有數(shù)據(jù)的情況下調(diào)用該函數(shù),則當(dāng)前線程會(huì)被掛起,直到有數(shù)據(jù)為止。

 

非阻塞函數(shù):指操作啟動(dòng)之后,如果可以立即得到結(jié)果就返回結(jié)果,否則返回表示結(jié)果需要等待的錯(cuò)誤信息,不等待任務(wù)完成函數(shù)就返回。

使用非阻塞I/O的方式:select()

例子:

while(1){//執(zhí)行循環(huán) 一邊輸出一邊也不要忘了輸入

              FD_ZERO(&wt_set); FD_ZERO(&rd_set);

              FD_CLR(s,&wt_set); FD_CLR(s,&rd_set);

              FD_SET(s,&wt_set); FD_SET(s,&rd_set);

          timeout.tv_sec = 0;

              timeout.tv_usec =500000;

                 z=select(s+1,&rd_set,&wt_set,NULL,&timeout);

            if(FD_ISSET(s,&rd_set)){//有數(shù)據(jù)可讀

                          z=recv(s,&recvBuff,sizeof recvBuff-1,0);

2011-3-19

29/37

阻塞與非阻塞(2)

2011-3-19

30/37

Berkeley socket函數(shù)部分中,不涉及網(wǎng)絡(luò)I/O、本地端工作的函數(shù)是非阻塞函數(shù)

Berkeley socket函數(shù)部分中,網(wǎng)絡(luò)I/O的函數(shù)是可阻塞函數(shù),也就是它們可以阻塞執(zhí)行,也可以不阻塞執(zhí)行。這些函數(shù)都使用了一個(gè)socket,如果它們使用的socket是阻塞的,則這些函數(shù)是阻塞函數(shù);如果它們使用的socket是非阻塞的,則這些函數(shù)是非阻塞函數(shù)。

并發(fā)服務(wù)器

2011-3-19

31/37

TCP服務(wù)器端(并發(fā)服務(wù)器)

socket( )

bind( )

listen( )

accept( )

send( )

recv( )

close( )

fork( ) //派生新進(jìn)程

close( )

主進(jìn)程在accept之后派生新進(jìn)程,然后主進(jìn)程繼續(xù)listen,處理新的連接請(qǐng)求

     新進(jìn)程自行和客戶端通信,新進(jìn)程和主進(jìn)程搶占CPU

WinSock API

2011-3-19

32/37

WinSock是一個(gè)基于Socket模型的API,在Microsoft Windows操作系統(tǒng)類中使用。

它在Berkeley接口函數(shù)的基礎(chǔ)之上,還增加了基于消息驅(qū)動(dòng)機(jī)制的Windows擴(kuò)展函數(shù)。

Winscok1.1只支持TCP/IP網(wǎng)絡(luò),WinSock2.0增加了對(duì)更多協(xié)議的支持。

Windows下的Socket編程(1)

2011-3-19

33/37

linux下基本相同,需要包含winsock2.h

需要使用Ws_32.lib,可以用以下語(yǔ)句通告程序編譯時(shí)調(diào)用該庫(kù):

    #pragma comment(lib,"Ws2_32.lib") ;

WinSockDLL的形式提供,在調(diào)用任何WinSock API之前,必須調(diào)用函數(shù)WSAStartup()進(jìn)行初始化,最后,調(diào)用函數(shù)WSACleanUp()作清理工作。

Windows下的Socket編程(2)

2011-3-19

34/37

WSADATA wsd;

//設(shè)置WINSOCK的版本

WORD wVersionRequested=MAKEWORD(2,2);

WSAStartup(wVersionRequested,&wsd) ; //初始化

 。。。。。。。。。    

 WSACleanUp();

Windows下的Socket編程(3)

2011-3-19

35/37

MFC提供了兩個(gè)類CAsyncSocketCSocket來(lái)封裝WinSock API,提供了更簡(jiǎn)單的網(wǎng)絡(luò)編程接口。

CAsyncSocket在較低層次上封裝了WinSock API,缺省情況下,使用該類創(chuàng)建的socket是非阻塞的socket,所有操作都會(huì)立即返回,如果沒(méi)有得到結(jié)果,返回WSAEWOULDBLOCK,表示是一個(gè)阻塞操作。

Windows下的Socket編程(4)

2011-3-19

36/37

CSocketCAsyncSocket的派生類,缺省情況下使用該類創(chuàng)建的socket是非阻塞的socket,但是CSocket的網(wǎng)絡(luò)I/O是阻塞的,它在完成任務(wù)之后才返回。

CSocket的阻塞不是建立在“阻塞”socket的基礎(chǔ)上,而是在“非阻塞”socket上實(shí)現(xiàn)的阻塞操作

網(wǎng)絡(luò)編程作業(yè)要求

2011-3-19

37/37

 

不分組,每人獨(dú)立完成。

基于C/SP2P結(jié)構(gòu),使用UDPTCP協(xié)議皆可。

最好使用基本SOCKET API,不反對(duì)使用CAsyncSocket

   CSocket類,但不準(zhǔn)使用和傳輸相關(guān)的控件。

期末提交設(shè)計(jì)文檔,源碼,及可執(zhí)行文件。

提交時(shí)間為12月份,具體提交日期及提交方式待定。

可選題目I

BBS發(fā)帖程序

通過(guò)term方式(202.38.64.3:23)或者通過(guò)web方式

完成在test版發(fā)一貼的功能(多發(fā)會(huì)被永久封賬號(hào))

Bbs賬號(hào)和密碼使用命令行參數(shù)或其他方式設(shè)置,不要直接寫在程序里

對(duì)于term方式下的程序,要求能監(jiān)視程序運(yùn)行過(guò)程(也就是說(shuō)在程序運(yùn)行的時(shí)候要把服務(wù)器的輸出打印到屏幕)

Referrence:

http協(xié)議:http://en.wikipedia.org/wiki/HTTP

2011-3-19

38/37

可選題目II

完成一個(gè)HTTP服務(wù)器

使用HTTP 1.1協(xié)議

支持最大至少10個(gè)并發(fā)連接(fork創(chuàng)建子進(jìn)程)

要求服務(wù)器程序運(yùn)行以后,能在瀏覽器中訪問(wèn)文件,正常顯示

Web server的根目錄使用命令行參數(shù)或者其他方式制定,不要寫在程序代碼里

文件不存在時(shí)返回瀏覽器404錯(cuò)誤

2011-3-19

39/37

2011-3-19

40/37

謝謝

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
網(wǎng)絡(luò)socket編程指南
Linux環(huán)境下的Socket編程 - C&C - Linux技術(shù)中堅(jiān)站
Linux編程常用的函數(shù)(八) 網(wǎng)絡(luò)編程
[ 永遠(yuǎn)的UNIX > Linux網(wǎng)絡(luò)編程--2. 初等網(wǎng)絡(luò)函數(shù)介紹(TCP) ]
Linux環(huán)境下的網(wǎng)絡(luò)編程
udp客戶端和服務(wù)代碼
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服