亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1078 | 回復: 0
打印 上一主題 下一主題

Socket [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2008-08-20 11:59 |只看該作者 |倒序瀏覽

Socket
Socket是TCP/IP網(wǎng)絡的API, 可以用它來開發(fā)網(wǎng)絡應用程序
Socket數(shù)據(jù)傳輸是一種特殊的I/O, Socket也是一種文件描述符
.Socket的建立
int socket(int domain,  int type,  int protocol)
函數(shù)返回:
          一個整型的Socket描述符, 可以在后面調(diào)用它
參數(shù)說明:
          int domain     指明所使用的協(xié)議族, 通常是PF_INET, 表示網(wǎng)絡(TCP/IP)協(xié)議族
                         說明我們網(wǎng)絡程序所在的主機采用的通訊協(xié)族(AF_UNIX和AF_INET等).
              AF_UNIX :  只能夠用于單一的Unix系統(tǒng)進程間通信,
              AF_INET :  是針對Internet的,因而可以允許在遠程主機之間通信
             (當我們man socket時發(fā)現(xiàn)domain可選項是 PF_*而不是AF_*,因為glibc是posix的實現(xiàn)所以用PF代替了AF,不過我們都可以使用的)
          int type       指定socket的類型, 通常是 SOCK_STREAM 流式Socket這樣會提供按順序的,可靠,雙向,面向連接的比特流和SOCK_DGRAM數(shù)據(jù)報式Socket這樣只會提供定長的,不可靠,無連接的通信
          int prottocol  通常為0 由于我們指定了type,所以這個地方我們一般只要用0來代替就可以了
應用示例:
          int sockfd = socket(PF_INET,  SOCK_STREAM, 0);
.Socket配置
  Socket描述符是一個指向內(nèi)部數(shù)據(jù)結構的指針,它指向描述符表入口。調(diào)用Socket函數(shù)時,
socket執(zhí)行體將建立一個Socket,實際上"建立一個Socket"意味著為一個Socket數(shù)據(jù)結構分配存儲空間。
Socket執(zhí)行體為你管理描述符表。
  兩個網(wǎng)絡程序之間的一個網(wǎng)絡連接包括五種信息:通信協(xié)議、本地協(xié)議地址、本地主機端口、遠端
主機地址和遠端協(xié)議端口。Socket數(shù)據(jù)結構中包含這五種信息。
  通過socket調(diào)用返回一個socket描述符后,在使用socket進行網(wǎng)絡傳輸以前,必須配置該socket:
     1)面向連接的socket客戶端通過調(diào)用Connect函數(shù)在socket數(shù)據(jù)結構中保存本地和遠端信息。
     2)無連接socket的客戶端和服務端以及面向連接socket的服務端通過調(diào)用bind函數(shù)來配置本地信息。
   Bind函數(shù)將socket與本機上的一個端口相關聯(lián),隨后你就可以在該端口監(jiān)聽服務請求。
   Bind函數(shù)原型為:
      int bind(int sockfd,struct sockaddr *my_addr, int addrlen);
Bind()函數(shù)在成功被調(diào)用時返回0;出現(xiàn)錯誤時返回"-1"并將errno置為相應的錯誤號。
     Sockfd     是調(diào)用socket函數(shù)返回的socket描述符,
        my_addr   是一個指向包含有本機IP地址及端口號等信息的sockaddr類型的指針;
        addrlen   常被設置為sizeof(struct sockaddr)。
       1) struct sockaddr結構類型是用來保存socket信息的:
         struct sockaddr
         {
          unsigned short sa_family;   /* 地址族, AF_xxx */
           char sa_data[14];           /* 14 字節(jié)的協(xié)議地址 */
          };
        sa_family    一般為AF_INET,代表Internet(TCP/IP)地址族;
         sa_data       則包含該socket的IP地址和端口號。
      2) sockaddr_in結構類型:
        struct sockaddr_in
         {
          short int sin_family;          /* 地址族 */
          unsigned short int sin_port;   /* 端口號 */
          struct in_addr sin_addr;       /* IP地址 */
          unsigned char sin_zero[8];     /* 填充0 以保持與struct sockaddr同樣大小sin_zero用來將sockaddr_in結構填充到與struct sockaddr同樣的長度,可以用bzero()或memset()函數(shù)將其置為零。 */
        };
        這個結構更方便使用。
         指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉換,這意味著如果一個函數(shù)所需參數(shù)類型是sockaddr時,你可以在函數(shù)調(diào)用的時候將一個指向sockaddr_in的指針轉換為指向sockaddr的指針;或者相反。
使用bind函數(shù)時,可以自動獲得本機IP地址和隨機獲取一個沒有被占用的端口號:
       /* 系統(tǒng)隨機選擇一個未被使用的端口號;通過將my_addr.sin_port置為0,函數(shù)會自動為你選擇一個未占用的端口來使用 */
     my_addr.sin_port        = 0;        
      /* 填入本機IP地址;通過將my_addr.sin_addr.s_addr置為INADDR_ANY,系統(tǒng)會自動填入本機IP地址 */   
     my_addr.sin_addr.s_addr = INADDR_ANY;   
   注意在使用bind函數(shù)是需要將sin_port和sin_addr轉換成為網(wǎng)絡字節(jié)優(yōu)先順序;而sin_addr則不需要轉換。
  計算機數(shù)據(jù)存儲有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先:
   Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡上傳輸,所以對于在內(nèi)部是以低位字節(jié)優(yōu)先方式存儲數(shù)據(jù)的機器,在Internet上傳輸數(shù)據(jù)時就需要進行轉換,否則就會出現(xiàn)數(shù)據(jù)不一致。
  下面是幾個字節(jié)順序轉換函數(shù): (h: host   n: network  l: long  s: short)
     ·htonl():把32位值從主機字節(jié)序轉換成網(wǎng)絡字節(jié)序, 轉為高位字節(jié)優(yōu)先
     ·htons():把16位值從主機字節(jié)序轉換成網(wǎng)絡字節(jié)序, 轉為高位字節(jié)優(yōu)先
     ·ntohl():把32位值從網(wǎng)絡字節(jié)序轉換成主機字節(jié)序, 從高位字節(jié)優(yōu)先轉換
     ·ntohs():把16位值從網(wǎng)絡字節(jié)序轉換成主機字節(jié)序, 從高位字節(jié)優(yōu)先轉換
   需要注意的是,在調(diào)用bind函數(shù)時一般不要將端口號置為小于1024的值,因為1到1024是保留端口號,你可以選擇大于1024中的任何一個沒有被占用的端口號。
   應用示例:
      A)服務端
         1)建立結構變量
         struct  sockaddr_in  my_addr;
         int     SERVPORT;
   
         2)配置協(xié)議族、端口、地址、sin_zero填充位
         my_addr.sin_family      = AF_INET;
         my_addr.sin_port        = htons(SERVPORT);
         my_addr.sin_addr.s_addr = INADDR_ANY;
         bzero(&(my_addr.sin_zero), 8);
      
         3)把sockfd的本地端口、IP地址、連接協(xié)議進行綁定
         if( bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1)
         {
            perror("bind");
            return 1;
         }
         
     
     B)客戶端
       1)建立結構體變量和端口號
       struct  sockaddr_in   serv_addr;
       struct  hostent *host;   
       int     SERVPORT;
       //struct hostent *host;   把服務器端IP通過gethostbyname賦給host結構體,如果傳入的是域名則轉為IP地址再賦值
       if((host = gethostbyname(“www.800hr.com”)) == NULL)   
       //或 if((host = gethostbyname(“192.168.0.1”)) == NULL)
       {
           herror("gethostbyname error");
           return 1;
       }
       else
       {//輸出IP地址: xxx.xxx.xxx.xxx
           printf("host: %s\n", inet_ntoa(*((struct in_addr*)host->h_addr)));
       }
      
       2)建立Socket
       if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
       {
          perror("create sock");
          return 1;
       }

       3)給服務端結構變量賦值
       serv_addr.sin_family = AF_INET;
       serv_addr.sin_port   = htons(SERVPORT);
       serv_addr.sin_addr   = *((struct in_addr *)host->h_addr);
       bzero(&(serv_addr.sin_zero), 8);
       4)連接服務端
       //int connect(int socfd,  struct sockaddr *serv_addr,  int addrlen)
       進行客戶端程序設計無須調(diào)用bind(),因為這種情況下只需知道目的機器的IP地址,而客戶通過哪個端口與服務器建立連接并不需要關心,socket執(zhí)行體為你的程序自動選擇一個未被占用的端口,并通知你的程序數(shù)據(jù)什么時候到達端口
      Connect函數(shù)啟動和遠端主機的直接連接。只有面向連接的客戶程序使用socket時才需要將此socket與遠端主機相連。
      面向連接的服務器從不啟動一個連接,它只是被動的在協(xié)議端口監(jiān)聽客戶的請求。
      無連接協(xié)議從不建立直接連接。
       if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
       {
           perror("create sock");
           return 1;        
       }
      
.Listen()
Listen函數(shù)
  1) 使socket處于被動的監(jiān)聽模式
  2) 為該socket建立一個輸入數(shù)據(jù)隊列,將到達的服務請求保存在此隊列中,直到程序處理它們
  int listen(int socfd,  int backlog)
  參數(shù)說明:
          sockfd   是socket()函數(shù)返回的socket描述符
          backlog  指定在請求隊列中允許的最大請求數(shù), 進入的連接請求將在隊列中等待accept它們
                   如果一個服務請求到來時,輸入隊列己滿, 此socket將拒絕連接請求,客戶收到一個出錯信息

    int BACKLOG = 20;
    if(listen(sockfd, BACKLOG) == -1)
    {
        perror("listen");
        return 1;
    }
.accept()
  在建立好輸入隊列后,服務器就調(diào)用accept函數(shù),然后睡眠并等待客戶的連接請求
  1) accept() 函數(shù)讓服務器接收客戶的連接請求。
  int accept(int sockfd,  void *addr,  int *addrlen);
  參數(shù)說明:
          sockfd   被監(jiān)聽的socket描述符
          addr     sockaddr_in變量的指針, 該變量用來存放請求服務的客戶機的信息
          addrlen  通常是sizeof(struct sockaddr_in)
  返回值 :
          -1         出錯時
          client_fd  成功時
  [注]    當accept函數(shù)監(jiān)視的socket收到連接請求時,socket執(zhí)行體將建立一個新的socket,執(zhí)行體將這個新socket和請求連接進程的地址聯(lián)系起來,收到服務請求的初始socket仍可以繼續(xù)在以前的 socket上監(jiān)聽,同時可以在新的socket描述符上進行數(shù)據(jù)傳輸操作
      
        int client_fd;
        sin_size = sizeof(struct sockaddr_in);
        if((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr.sin_addr, &sin_size)) == -1)
        {
            perror("accept");
            continue;
        }
.send()
int  send(int sockfd,  const  void *msg,  int len,  int  flags);
參數(shù)列表:
          sockfd   接收數(shù)據(jù)的socket方的id
          msg      要發(fā)送數(shù)據(jù)的指針
          len      以字節(jié)為單位的數(shù)據(jù)的長度
          flags    一般為0
返回值 :
          失敗     -1
          成功     發(fā)送成功的字節(jié)數(shù)
示 例:
          char *msg = "Hello!";
          int len, bytes_sent;
          ....
          len = strlen(msg);
          bytes_sent = send(client_fd, msg,len,0);
          ...

.recv()
int  recv(int sockfd,  void *buf,  int len,  unsigned  int flags);
參數(shù)列表:
         sockfd      接收數(shù)據(jù)的socket的fd
         buf         存放數(shù)據(jù)的數(shù)據(jù)緩沖區(qū)
         len         len是緩沖的長度
         flags       通常為0
返回值  :
         成功         實際接收的字節(jié)數(shù)
         錯誤         -1
    while(1)
    {
        recvbytes = recv(sockfd, buf, MAXDATASIZE, 0);
        if(recvbytes

本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/20619/showart_1134753.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP