套接口socket編程(Client/Server編程實例)


基本概念                                                                                                                                         

套接口也就是網絡中的ID。網絡通信,歸根到底還是進程間通信(不同計算機上的進程間的通信)。在網絡中,每一個節點(計算機或路由器)都有一個網絡地址,也就是IP地址。

  • IP地址:在網絡中唯一標識一台主機,32
  • 端口號:在主機中唯一標識一個進程,16
  • IP+port:在網絡環境中唯一標識一個進程(socket)

      socket也稱套接字,是linux文件的一種類型(偽文件:不占存儲空間的文件。linux 有7中文件, 1.普通文件  2.目錄(d)3.字符設備文件(c) 4.塊設備文件(b) 5.套接口文件(s)[如我們開啟MySQL服務后,在/var/lib/mysql/下生成的mysql.sock文件,關閉MySQL服務后,這個文件就消失了],6.管道(p):有兩端,讀端 r:流出 fd[0]     寫段w:流入 fd[1]         7.符號鏈接文件(l)[有點兒像WIN下的快捷方式]  其中占存儲的有三種:普通,目錄,軟鏈接)

       socket成對出現,

       一個文件描述符指向兩個緩沖區,一個讀一個寫。

預備知識                                                                                                                                          、

網路字節序:

       TCP/IP規定,網路數據流應采用大端字節序,即低地址高字節。(大端:低地址--高位   高地址--地位    小端:低--低 高--高,即端口號和IP地址都是以網路字節序存儲的,網絡字節序使用的是大端模式。稱給某個系統所采用的字節序為主機字節序,它可能是小端模式也可能是大端模式。

       為使網絡編程具有可移植性,使同樣的C代碼在大端和小端計算機上編譯后能正常運行,可以調用一下庫函數做網絡字節序和主機字節序的轉換。

#include<arpa/inet.h>
uint32_t  htoal(uint32_t hostlong);
uint16_t  htons(uint16_t hostshort);
//返回的是網絡字節序
uint32_t ntoh1(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//返回的主機字節序
//h表示host,to,n代表network,s代表short,l表示long
//端口16位 ,ip 32位

 套接口的數據結構                                                                                                                                

      在Linux中,每一種協議都有自己的網絡地址數據結構,以sockaddr_開頭,如IPV4對應的是sockaddr_in.

           //man 7 ip 查看

           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
            /*套接口結構地址族,如IPV4為AF_INET*/
               in_port_t      sin_port;   /* port in network byte order */
            /*16位TCP或UDP端口號,網絡字節順序*/
               struct in_addr sin_addr;   /* internet address */
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };

C/S編程                                                                                                                                                  

服務器是指在網絡上提供服務的應用程序,客戶機是指用戶為了得到某種服務所需要 運行的應用程序,即申請服務的程序。一個服務器程序可以同時接收多個客戶機的請求。

 

server.c:
socket() 建立套接字
bind()  綁定IP 端口號(struct sockaddr_in addr 初始化)
listen() 指定最大同時發起連接數
accept()  阻塞等待客戶端發起連接
read()
小--大
write 給客戶端
close();

 

client.c:
socket();
bind();可以依賴“隱式綁定”,即寫不寫都行
connect();發起連接
write();
read();
close();
 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/socket.h>
 4 #include<stdlib.h>
 5 #include<arpa/inet.h>
 6 #include<ctype.h>
 7 #include<strings.h>
 8 #define SERV_PORT 6666 //端口號
 9 int main(void)
10 {
11    int lfd,cfd;//定義套接口描述符
12    struct sockaddr_in serv_addr;//定義服務器IPV4套接口地址數據結構serv_addr
13    struct sockaddr_in clie_addr;//d定義客戶端client
14    socklen_t clie_addr_len;
15    char buf[BUFSIZ],clie_IP[BUFSIZ];//用BUFSIZ就不需要自己定義宏了
16    int i,n;
17    lfd=socket(AF_INET,SOCK_STREAM,0);//AF_INET:IPV4 AF_INET6:IPV6
18    bzero(&serv_addr,sizeof(serv_addr));//清0,memset清任何數 
19    serv_addr.sin_family=AF_INET;//設置addr的成員信息
20    serv_addr.sin_port=htons(SERV_PORT);//本地字節序轉換為網絡字節序
21    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);//IP地址設為本地IP INADDR_ANY本地任意IP
22 
23    bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//綁定端口
24 
25    listen(lfd,128);//最多可以接受128個客戶端的請求,監聽ifd描述符
26 
27    clie_addr_len=sizeof(clie_addr);
28    cfd=accept(lfd,(struct sockaddr *)&clie_addr,&clie_addr_len);//bind accept connect 需要強轉
29    printf("client IP:%s,client port:%d\n",inet_ntop(AF_INET,&clie_addr.sin_addr,clie_IP,sizeof(clie_IP)),ntohs(clie_addr.sin_port));
30    while(1){
31    n= read(cfd,buf,sizeof(buf));
32    for(i=0;i<n;i++)
33    {
34      buf[i]=toupper(buf[i]);//下寫轉換為大寫
35    }
36    write(cfd,buf,n);
37    }
38    close(lfd);
39    close(cfd);
40 
41    return 0;
42 
43 }
server.c
 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/socket.h>
 4 #include<stdlib.h>
 5 #include<arpa/inet.h>
 6 #include<ctype.h>
 7 #include<string.h>
 8 #define SERV_PORT 6666
 9 #define SERV_IP "127.0.0.1 "
10 int main(void)
11 {
12     int cfd;
13     int n;
14     char buf[BUFSIZ];
15     struct sockaddr_in serv_addr;
16    // socklen_t serv_addr_len;
17     cfd = socket(AF_INET,SOCK_STREAM,0);
18     memset(&serv_addr,0,sizeof(serv_addr));
19     serv_addr.sin_family=AF_INET;//設置addr的成員信息
20     serv_addr.sin_port=htons(SERV_PORT);//本地字節序轉換為網絡字節序
21     inet_pton(AF_INET,SERV_IP,&serv_addr.sin_addr.s_addr);
22  //    serv_addr.sin_addr=*((struct in_addr *)host->haddr);
23     connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//客戶端程序發起連接請求
24    while(1)
25    {
26    fgets(buf,sizeof(buf),stdin);//hello world ----fgets---"hello world\n\0"從鍵盤寫 
27    write(cfd,buf,strlen(buf));
28    n=read(cfd,buf,sizeof(buf));
29    write(STDOUT_FILENO,buf,n);
30    }
31    close(cfd);
32    return 0;
33 }
client.c

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM