網絡編程基礎+UDP的實現

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

A類地址:第一個字節爲網絡地址,其餘3個字節主機地址,第一字節的最高位固定爲0服務器

1.0.0.1------126.255.255.255網絡

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

128.0.0.1---191.255.255.255tcp

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

192.0.0.1----223.255.255.255測試

D類地址:組播地址spa

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

224.0.0.1-----239.255.255.255code

注意幾點:

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

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

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

 

 

幾種常見的網絡分包格式

1、 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和端口號。

 

2、 udp數據包格式:

 

tcp差很少,只是傳輸層的協議改爲了udp,面向不連接。

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

幾種常見的網絡分包格式

3、 廣播udp數據包格式:

 

 

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

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

二、 在網絡層目標ip地址爲:192.168.1.255

 

4、 組播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)//二、、、、、、綁定本機的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

}
相關文章
相關標籤/搜索