Linux——网络编程基础 UDP对等模型编程

一.网络
    1.基础(ip)
        1.1.网络工具
            ping
            ping ip地址
            ping -b ip广播地址
            ifconfig -a                
            
            netstat -a
            netstat -u
            netstat -t
            netstat -x
            netstat -n
            
            route
            lsof
        1.2.网络的基本概念
            网络编程采用socket模型.
            网络通信本质也是进程之间的通信。只是在不同主机之间的进程通信。
            
            识别主机:4字节整数:IP地址
            识别进程:2字节整数:端口号
                    
            IP地址的三种表示方法:    
            内部表示:4字节整数
            外部表示:数点字符串 例如"192.168.0.26"
            结构体表示
                struct in_addr
                {
                    in_addr_t  s_addr;
                    }        
            
            //总结:
            IP地址的表示
                字符串表示"192.168.0.26"
                整数表示:in_addr_t;
                字结构表示struct in_addr;
            连接点:endpoint
            struct sockaddr_in
            {
                in_port_t     sin_port;
                struct in_addr  sin_addr;
            };
        1.3.IP地址的转换
            inet_addr       //把字符串转换为整数(网络字节序)
            inet_aton    //把字符串转换为结构体 struct in_addr;(网络字结序)            
            #inet_network    //把字符串转换为整数(本地字节序)            
            inet_ntoa    //把结构体转换为字符串            
            htons
            htonl            
            ntohs
            ntohl
            使用的时候要使用网络字节序
            
        1.4.IP地址的意义    
            IP地址的位表达不同意义:
            
            IP地址组建网络:网络标识/主机标识
                网络(位)    主机(位)
            A类     7         24        网络少  主机多
            B类     14         16                     
            C类     21         8    
            D类    组播    

            E类     没有使用

inet.c

<span style="font-size:18px;">#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main()
{
	
// 	in_addr_t  nip=192<<24 | 168 <<16 | 0<<8 | 26;//4字节无符号整数格式
// 	char  *ip="192.168.0.26";//字符串格式
// 	
// 	struct in_addr sip;//结构体格式
// 	sip.s_addr=nip;
// 	
// 	printf("nip:%u\n",nip);
// 	
// 	printf("%s\n",inet_ntoa(sip));//结构体转换成字符串
// 	
// 	int myip;	
// 	myip=inet_addr(ip);//字符串转换成整数
// 	printf("%u\n",myip);
// 	
// 	printf("%hhu.%hhu.%hhu.%hhu\n",	myip>>24 & 255,
// 					myip>>16 & 255,
// 					myip>>8  & 255,
// 					myip>>0  & 255);
	
	/*
	char ip[4]={192,168,0,26};
	printf("%d\n",*(int*)ip);
	*/
	char *ip="10.45.8.1";
	struct in_addr addr;
	in_addr_t net;
	in_addr_t host;
	struct in_addr tmp;
	
	inet_aton(ip,&addr);//把字符串转换为结构体
	
	host=inet_lnaof(addr);//得到主机号
	net=inet_netof(addr);//得到网络号
	
	tmp.s_addr=net;
	
	printf("%s\n",inet_ntoa(tmp));//得到网络地址
	
	tmp.s_addr=host;
	printf("%s\n",inet_ntoa(tmp));//得到主机地址
	
}
</span>


            
        1.5.计算机系统中的网络配置
            /etc/hosts文件  配置IP,域名,主机名
                        gethostbyname
                        gethostbyaddr
            /etc/protocols文件  配置系统支持的协议
            /etc/services文件 配置服务的端口

            跟以上网络数据库有关的函数
            get***by***;            
            gethostbyname //          

            getprotobyname

host.c

<span style="font-size:18px;">#include <stdio.h>
#include <netdb.h>
main()
{
	struct hostent *ent;
	/*打开主机配置数据库文件*/
	sethostent(1);//打开/etc/hosts文件,可以是本机也可以是网络的
	while(1)
	{
		ent=gethostent();
		if(ent==0) break;
		
		printf("主机名:%s\t",ent->h_name);
		printf("IP地址:%hhu.%hhu.%hhu.%hhu\t",
				ent->h_addr[0],
				ent->h_addr[1],
				ent->h_addr[2],
				ent->h_addr[3]);
		printf("别名:%s\n",ent->h_aliases[0]);
	}
	endhostent();
}
</span>

getip.c

#include <stdio.h>
#include <netdb.h>
main()
{
	struct hostent *ent;
	ent=gethostbyname("www.baidu.com");//根据网站名返回IP地址
	//printf("%s\n",ent->h_aliases[0]);
	printf("%hhu.%hhu.%hhu.%hhu\n",
		ent->h_addr_list[0][0],
		ent->h_addr_list[0][1],
		ent->h_addr_list[0][2],
		ent->h_addr_list[0][3]);	
}

protocol.c

#include <stdio.h>
#include <netdb.h>
#include <sys/utsname.h>
main()
{
	struct protoent *ent;
	struct utsname name;
	ent=getprotobyname("tcp");//根据协议名返回协议结构体
	printf("%d\n",ent->p_proto);//协议号6
	
	uname(&name);//顺便介绍 获得本机系统的信息
	printf("%s\n",name.machine);
	printf("%s\n",name.nodename);
	printf("%s\n",name.sysname);
	printf("%s\n",name.version);
}
                     

    2.TCP/UDP编程

     socket函数的参数

            对等模型:AF_INET      SOCK_DGRAM          0(默认协议):UDP
            C/S 模型:AF_INET         SOCK_STREAM      0(默认协议):TCP

        2.0.网络编程
            ISO的7层模型:
                物理层                    
                数据链路层            数据链路层(数据物理怎么传输)
                网络层                    IP层            (数据的传输方式)
                传输层                    传输层       (数据传输的结果)                    
                会话层                    应用层            (数据传递的含义)
                表示层
                应用层
                                
        2.1.UDP编程的数据特点
                UDP采用对等模型SOCK_DGRAM
                socket                            socket:socket
                绑定IP地址bind         连接目标(可选)        conncect
                read/recv/recvfrom       发送数据    write/send/sendto
                关闭close            
案例:
        A:                                                        B
            接收用户的数据                         发送数据
            打印数据与发送者IP                接收数据并打印

            返发一个信息

 udpA.c//接收者 然后给发送者一个回应

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

main()
{
	int fd;//socket描述符号
	struct sockaddr_in ad;//本机的IP地址
	char buf[100];//接收数据缓冲
	
	struct sockaddr_in ad_snd;//发送者IP地址
	socklen_t len;//发送者IP的长度
	int r;
	
	fd=socket(AF_INET,SOCK_DGRAM,17);
	if(fd==-1) printf("socket:%m\n"),exit(-1);
	printf("建立socket成功!\n");
	
	ad.sin_family=AF_INET;
	ad.sin_port=htons(11111);
	inet_aton("192.168.1.116",&ad.sin_addr);
	r=bind(fd,(struct sockaddr*)&ad,sizeof(ad));
	if(r==-1) printf("bind err:%m\n"),exit(-1);
	printf("绑定成功!\n");
	
	while(1)
	{
		len=sizeof(ad_snd);
		r=recvfrom(fd,buf,sizeof(buf)-1,0,
				(struct sockaddr*)&ad_snd,&len);
		if(r>0){
			buf[r]=0;
			printf("发送者IP:%s,端口:%hu,数据:%s\n",
				inet_ntoa(ad_snd.sin_addr),
				ntohs(ad_snd.sin_port),buf);
			sendto(fd,"古怪!",strlen("古怪!"),0,
			(struct sockaddr*)&ad_snd,sizeof(ad_snd));
		}
		if(r==0)
		{
			printf("关闭!\n");			
			break;
		}
		if(r==-1)
		{
			printf("网络故障!\n");			
			break;
		}
	}
	
	close(fd);	
}

udpB.c//发送者

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main()
{
	int fd;
	struct sockaddr_in ad;
	char buf[101];
	int r;
	
	fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd==-1) printf("socket err:%m\n"),exit(-1);
	
	ad.sin_family=AF_INET;
	ad.sin_port=htons(11111);
	ad.sin_addr.s_addr=inet_addr("192.168.1.116");	
	//connect(fd,(struct sockaddr*)&ad,sizeof(ad));
	while(1)
	{
		r=read(0,buf,sizeof(buf)-1);
		if(r<=0) break;
		
		buf[r]=0;
		
		r=sendto(fd,buf,r,0,
				(struct sockaddr*)&ad,sizeof(ad));
		
		bzero(buf,sizeof(buf));
		r=recv(fd,buf,sizeof(buf),0);
		buf[r]=0;
		printf("来自接收方的数据:%s\n",buf);
		//r=send(fd,buf,r,0);		
		if(r==-1) break;
		
	}
	close(fd);
	
}


                              

            
        总结:
                1.connect + send  == sendto
                2.recvfrom的作用不是专门从指定IP接收,而是从任意IP接收数据,返回发送数据者的IP
                3.问题:
                        为什么要bind,bind主要目的告诉网络发送数据的目标.
                        是否一定绑定才能发送数据?
                        否:只要知道你的IP与PORT,就能发送数据.
                4.问题:
                        为什么发送者没有绑定IP与端口,他也有端口?
                        底层网络驱动,帮我们自动生成IP与端口.
                5.缺陷:
                        接收方不区分发送者的.        
                                
    send函数        
    sendto函数
            int sendto(
                    int fd,//socket描述符号
                    const void *buf,//发送的数据缓冲
                    size_t size,//发送的数据长度
                    int flags,//发送方式MSG_NOWAIT MSG_OOB
                    const struct sockaddr *addr,//发送目标的IP与端口
                    socklen_t len//sockaddr_in的长度
                );
            返回:
                    -1:发送失败
                    >=0:发送的数据长度
    recv函数
    recvfrom函数                    
            int recvfrom(
                    int fd,
                    void *buf,
                    size_t size,
                    int flags,
                    struct sockaddr*addr,//返回发送者IP与端口
                    socklen_t *len);//输入返回IP的缓冲大小,返回实际IP的大小                            
                
        2.2.TCP编程的数据特点
        2.3.TCP服务器的编程
    3.TCP的服务器编程模型
    4.IP协议与处理(SOCK_RAW,SOCK_PACKET)
    5.pcap编程
    6.HTTP协议与网页搜索
    
作业:
        1.重新编写UDP网络通信    
        2.使用gethostbyname的得到www.baidu.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值