网络编程基础+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

}

 

posted @ 2016-03-17 15:32  高傲的monkey  阅读(3959)  评论(0编辑  收藏  举报