高级编程之网络编程(一)

 

TCP/IP 协议族:常用协议

物理链路层: ARP  RARP  MTU
网络层:  IP   ICMP  RIP  OSPF  IGMP  ?
传输层:  TCP   UDP
应用层:  TFTP  HTTP  HTTPS  SNMP SMTP DNS


TCP 协议 ===》RFC 793
 TCP 传输控制协议: 有链接 可靠 实时
    
UDP 协议 ===》RFC 768
 UDP 用户数据报协议: 无链接 不可靠 不实时

www.rfc.org

网络地址划分:

A类网络:第一组表示网络,后面三组表示主机:      
二进制最高位必须是0开头 ,0xxxxxxx
十进制表示范围:1.0.0.0~126.0.0.0    127.0.0.0 是回环诊断用
默认掩码:       255.0.0.0
网络数:126个  每个子网主机数:1亿多

注意: 127.0.0.1 ===》本机的回还地址
       10.0.0.0 ===》10.255.25.255 A类网络的私有地址不会在互联网出现。


B类网络:前两组表示网络,后两组表示主机;
二进制最高位必须是10开头,10xxxxxx
十进制表示范围:128.0.0.0~191.255.255.255
默认掩码: 255.255.0.0
网络数:16382个,每个子网主机数6万多

互联网上不会出现的私有地址:
 172.16.x.x
 169.254.x.x

C类网络:前三组表示网络,后一组表示主机
二进制最高位必须是110开头,110xxxxx
十进制表示范围:192.0.0.0~223.255.255.255
默认掩码: 255.255.255.0
网络数:209万多个,每个子网主机数 254个

私有地址:
 192.168.x.x 局域网内部测试使用。


D类网络:二进制最高位必须是1110开头,1110xxxx
十进制表示范围:224.0.0.0~239.255.255.255
没有掩码
多点广播地址范围。

上网的流程:
0、物理链路链接正常。

1、liunux : 配置ip地址 ==》ifconfig ethX  x.x.x.x/24 up
   配置网关  ===>route -n  ==>route add default x.x.x.x
   检测链路: ping  8.8.8.8  ping 61.134.1.4
   配置DNS: vi  /etc/resolv.conf   ==>DNS 8.8.8.8
 

2、WINDOWS: 配置ip地址: 网络 ==》更该适配器设置==》以太网右键
        ==》属性====》TCP/IPv4 ===》属性

  配置:ip地址
     dns地址


============================================================
网络系统调用接口

1、socket ====>BSD socket ==>套接字
  分类:SOCK_STREAM  基于TCP协议的套接字  流式套接字
      SOCK_DGRAM   基于UDP协议的套接字  用户数据报套接字
     SOCK_RAW     原始套接字
 
2、IP+port 
 ip   IP地址 有(A,B,C,...)类
 port    应用程序对外的数字编号 范围如下
     TCP PORT  1-65535
     UDP PORT  1-65535

3、字节序
 大端存储 ===》数据的低端 === 内存的高端
 小端存储 ===》数据的低端 === 内存的低端

 头文件:  #include <arpa/inet.h>

数字:
 主机转网络字节序: htonl
         htons

 网络转主机字节序:  ntohl
      ntons


字符串:
 主机转网络字节序:inet_addr()
 网路转主机字节序:inet_ntoa()


网络编程之  TCP 编程  ==》C/S 模式

C: 客户端 ==》流程:

socket()==>bind(可选)===>connect()==>send()/recv() ===>close()

S: 服务器端

socket()==>bind()==>listen()==>accept()==>recv()/send() ==>close()


函数:

头文件
#include <sys/types.h>         
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
功能:通过该函数可以创建一个套接字通信文件。
参数:domain  地址族: PF_INET(AF_INET)  PF_UNIX(AF_UNIX)
   type    套接字类型:
      SOCK_STREAM   SOCK_DGRAM  SOCK_RAW
   protocol  0 表示有os自动匹配合适的协议。
返回值:成功 返回套接字 id  >0 的数字。相当与一个文件描述符。
     失败  -1;


int connect(int sockfd, const struct sockaddr *addr,
        socklen_t addrlen);
功能:该函数只能用于客户端链接服务器端使用。表示从本地创建
   的sockfd中发起链接到addr指向的服务器地址。
参数:sockfd 之前通过socket创建的套接字。
   addr 要链接的服务器地址。
   addrlen 要链接的服务器地址的长度。

返回值:成功  0
  失败  -1;

注意:struct sockaddr的类型如下:
 
  通用地址类型
  struct sockaddr
  {
   u_short sa_family;  协议族类型
   char sa_data[14];   14字节的地址信息
  };
 
  转换后的网络地址类型:
  struct sockaddr_in
  {
   u_short       sin_family;
   u_short         sin_port;
   struct in_addr   sin_addr;
   char      sin_zero[8];
  }

 struct in_addr
 {
  in_addr_t s_addr;  网络字节序的IP地址
 }

 要用该类型必须注意字节序转换:

发送/接受数据:

三组六对:

  send()/recv()      ===>TCP
  sendto()/recvfrom() ===>UDP
  write()/read    ===>IP


int send(int sockfd, const void *msg, size_t len, int flags);
功能:从msg所在的内存中取出len长度的数据写入到sockfd的套接字中。
参数: sockfd 要发送数据的套接子id
  msg  要发送的数据的来源
  len  要发送的数据长度
  flags 发送数据的方式 0 表示阻塞方式发送。
       MSG_DONTWAIT  表示非阻塞方式发送。
返回值:成功 发送数据长度
  失败  -1

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:从指定的sockfd套接子中获取长度为len的数据到buf内存中。
参数:sockfd 要获取数据的套接字id
   buff 要存储数据的本地内存
   len 要存储的数据长度,一般等于buff的大小。
   flags  接收方式,0 表示阻塞方式接受
返回值:成功 表示接受的数据长度,一般小于等于len
  失败 -1;


关闭:
  int  close(int fd);
  功能:关闭已经使用完毕的套接字id
  参数:套接字id
  返回值:成功 0 
    失败  -1;

服务器端:

socket()==>bind()===>listen()===>accept()===>recv()/send()===>close()


原型:int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
参数:sockfd 之前通过socket创建的套接字id
   my_addr 要bind的本地接口地址。
   addr    要bind的地址长度。
返回值:成功  0
  失败   -1;


注意:该函数的参数2 应该如下设置:
 1、先定义本地地址变量:struct sockaddr_in myaddr;
 2、给本地变量赋值:
   myaddr.sin_family  = PF_INET;
   myaddr.sin_port   = htons(8888);
   myaddr.sin_addr.s_addr  = inet_addr("192.168.0.100");
 

   socklen_t len = sizeof(myaddr);
 3、用该变量来bind到套接字:

  bind(sockfd,(struct sockaddr *)&myaddr,len);

int listen(int sockfd, int backlog);
功能:从sockfd对应的套接字中监控链接。
参数:sockfd 要监控的套机字id
   backlog  允许同时链接的客户端个数。
返回值:成功  0
  失败   -1;

原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:该函数有服务器端执行并将新链接接收入当前进程。
参数:sockfd要获取链接的本地套接字id
   addr  获取的客户端信息结构体。
       如果不关心客户端信息,则该值为NULL;
     如果要获取信息,则需要事先定义变量并传入地址。
   addrlen  参数3的长度的指针:
     socklen_t len  = sizoef(addr);    &len;

返回值:成功 返回一个新的套接字id用于以后的通信过程。
  失败  -1;

注意:该函数执行完毕,则后面的send  recv 的参数1 都用该函数返回值。


问题:
1、connect : No route to host
 
   解决: service iptables stop
 

2、bind: Address already in use
 
   解决: int on = 1;  ///将以下语句加在bind函数之前
     setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))


细节:
1、要获取客户端的信息:accept(sockfd,cliaddr,&len)
 的参数2 3 必须设置。

2、要使客户端从指定的端口发送数据。
 在客户端用  bind 函数


练习:

 通过TCP程序发送一个结构体信息,在另一端将该结构体成员
 变量的值都打印出来。
 假设结构如下:
 typedef struct
 {
  int id;
  char name[32];
  char pass[64];
 }STU;

 

作业:
 通过以上函数的学习,尝试完成如下功能:
 客户端可以给服务器发送一个指定的文件。
 服务器收到该文件并存储到指定位置。

 要求:尽量把文件的名称发过去。服务器要
   用同名文件存储。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值