網絡編程基礎+UDP的實現


網絡地址分類(32位網絡地址)

A類地址:第一個字節為網絡地址,其他3個字節主機地址,第一字節的最高位固定為0

1.0.0.1------126.255.255.255

B類地址:第一字節和第二字節為網絡地址,其他2個字節為主機地址,第一字節前兩位固定為10

128.0.0.1---191.255.255.255

C類地址:前三個字節為網絡地址,最后一個字節是主機地址,第一字節的前三位固定為110

192.0.0.1----223.255.255.255

D類地址:組播地址

不分網絡地址和主機地址,第一字節的前四位固定為1110

224.0.0.1-----239.255.255.255

注意幾點:

1192.168.1.255為廣播地址,任何主機都是不能使用的。

2、每一個網絡地址都能組成一個小型的局域網。

3127.0.0.1測試tcp,udp網絡時使用的內部回環網絡

 

 

幾種常見的網絡分包格式

一、 tcp數據包格式:

 

Ethernet header:網絡物理接口層(存放了網卡的MAC地址,共48位)

Ip header:網絡層,存放了目標主機的ip地址,源主機的ip地址

TCP:傳輸層,存放了目標主機的port號和源主機的port號。這層確定傳輸是否可靠

Ethernet trailer:對傳輸的數據進行CRC校驗

 

發送過程:應用層—>加個應用層頭-à加個tcp---》加個ip---》加個ethernet (指定mac地址)---》最后對數據進行CRC校驗。

 

接收過程:反方向砍掉各種各樣的頭,先進行CRC校驗---》驗證MAC地址,如果匹配,則將其砍掉---》驗證主機ip地址、匹配,將其砍掉----》驗證tcpport,匹配將其砍掉---》最后只剩下數據了。

 

Accept的第二個參數填放了目標主機的ip和端口號。

 

二、 udp數據包格式:

 

tcp差不多,只是傳輸層的協議改成了udp,面向不鏈接。

Sendto的倒數第二個參數填放了目標主機的ip及端口等信息

幾種常見的網絡分包格式

三、 廣播udp數據包格式:

 

 

udp數據包有兩個地方的區別:

1、 分別是mac地址為FF :FF: FF: FF:FF:FF整個四十八位全為1

2、 在網絡層目標ip地址為:192.168.1.255

 

四、 組播udp數據包格式:

 

與廣播udp數據包格式的區別主要在mac:組播數據包的mac目標地址為:[0 00500]前面為高25位,低23位為目標ip的低23位,這樣的話,只要目標ip沒有加入到組播,mac地址首先就無法匹配,這樣大大提高了數據的傳輸效率,不用每次都需要匹配到udp 的傳輸層才能判斷出是否要發送數據。

 

UDP的通信的范例
編程步驟:
服務器(收數據):
1、創建socket(socket())得到socketfd
2、綁定本機ip(bind())一般綁定宏ip
3、先接受數據得到對方的ip和port(recvfrom())
4、發送數據(sendto())
5、關閉socketfd(close())

(發送數據)
1、創建socket(socket())得到socketfd
2、初始化對方主機的ip和端口號
3、發送數據(sendto)倒數第二參數為對方的ip和port號
4、接受數據
5、關閉socket(close())


服務器:
#include<stdio.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include<strings.h>

int main()
{    int socketfd = socket(AF_INET,SOCK_DGRAM,0);//、、、、1.創建udp套接字socket得到socketfd
    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
//此處可以使用宏ip(=htonl(INADDR_ANY))該宏ip為一個整型數z轉化為二進制L==long
    saddr.sin_addr.s_addr = inet_addr("192.168.193.2");
    if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0)//2、、、、、、綁定本機的ip地址
        perror("bind() error!\n");
    
    struct sockaddr_in caddr;
    int s = sizeof(struct sockaddr);    
    char buf[20],buf1[20];
    int n;
    while(1)//、、、、、、、、、、、、、、、、、、、、、、、、3.收發數據
    {    
        bzero(buf,20);
        //scanf("%s",buf);    
        if(n = recvfrom(socketfd,buf,20,0,(struct sockaddr *)&caddr,&s)<0)//recvfrom的倒數第二個參數為對方的ip和端口號,recvfrom函數自動獲取,因此sendto中的地址就填該結構體。
            perror("send() error!\n");
            printf("%s",buf);
            fgets(buf1,20,stdin);
        sendto(socketfd,buf1,strlen(buf),0,(struct sockaddr *)&caddr,s);
    }    
    close(socketfd);//、、、、、、、、、、4.關閉套接字socketfd

}
客戶端:
#include<stdio.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include<strings.h>

int main()
{    
int socketfd = socket(AF_INET,SOCK_DGRAM,0);//、、、、、、、1.創建udp套接字得到socketfd文件描述符
    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("192.168.193.2");//、、、2.初始化結構體sockaddr_in 目標主機的ip,sendto的倒數第二個參數

    
    struct sockaddr_in caddr;
    int s = sizeof(struct sockaddr);    
    char buf[20],buf1[20];
    int n;
    while(1)//、、、、3.發送接收數據.
    {    
        //bzero(buf,20);    
        fgets(buf,20,stdin);
        if(n = sendto(socketfd,buf,strlen(buf),0,(struct sockaddr *)&saddr,s)<0)
            perror("recv() error!\n");
        //    printf("%d\n",n);
        bzero(buf1,20);
        recvfrom(socketfd,buf1,20,0,(struct sockaddr *)&caddr,&s);
        printf("%s",buf1);
    }    
    close(socketfd);//、、、4.關閉socketfd

}

 


免責聲明!

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



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