跨网段交换数据
当192.168.0.2计算机(A)向192.168.1.2计算机(B)发送一条消息的时候:
1、A先将目的地址和本计算机的子网掩码进行按位与。
2、A计算机把按位与的结果和自己的路由表进行对比,发现目标地址不是本网段地址。在路由表中也没有这个网络号的路由
3、A计算机将默认网关(192.168.0.1)的mac地址填写到网帧头部的目标地址中,把消息发送到默认网关
4、默认网关收到消息之后,对比IP数据报的头部的目的地址发现不是自己,也不是本网段的,于是查询路由器的IP路由表,将192.168.1.1的mac地址记录到网帧头部的目标地址中,发送给192.168.1.1
5、192.168.1.1收到消息之后,发现目标地址不是自己,但是是本网段的地址,于是通过查询自己的arp表,将目标地址对应的mac地址记录到网帧的头部。发送出去
6、最后B计算机收到了这条消息。
网络通讯—–一个客户端和一个服务端的通讯
服务端:
以TCP的方式为例
服务端要为一个网络通讯做如下的准备:
1、建立一个通讯端点
socket
2、将通讯端点和具体的地址和端口进行绑定
bind
3、将通讯端点设置为被动状态,一直监听端口,维护一个未决连接队列
listen
4、从未决连接队列中获取第一个连接,如果队列中没有连接,进入阻塞状态
accept
5、接受客户端传过来的信息
read
6、处理客户端信息
7、将处理后的信息发送给客户端
write
8、断开连接
close
客户端要为一个网络通讯做如下的准备:
1、建立一个通讯端点
socket
2、向服务器发起一个连接请求
connect
3、请求通过后,向服务端发送数据
write
4、阻塞等待服务端处理数据
read
5、收到服务端处理完的数据之后,处理数据
6、关闭连接
close
下面两段代码,分别演示客户端、服务端
/*server.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(void){
char buf[1024];
//用于和客户端连接的文件描述符
int fd_accept;
//声明一个IPV4地址家族类型的变量,这个变量是具体的通讯地址,包括IP地址和端口号
struct sockaddr_in serv;
//创建一个通讯端点
int fd_socket = socket(AF_INET,SOCK_STREAM,0);
if(fd_socket == -1){
perror("socket");
return -1;
}
//初始化serv
//使用的地址家族
serv.sin_family = AF_INET;
//端口号
serv.sin_port = htons(6666);
//ip地址
inet_pton(AF_INET,"176.20.35.70",&(serv.sin_addr));
serv.sin_addr.s_addr = htonl(INADDR_ANY);
//绑定一个具体的addr绑定在socket上
int fd_bind = bind(fd_socket,(struct sockaddr *)&serv,sizeof(struct sockaddr_in));
if(fd_bind == -1){
perror("bind");
return -1;
}
//将socket设置为被动连接,当有连接到来的时候,将连接放入未决连接队列中
listen(fd_socket,5);
while(1){
//从未决连接队列中取出一个连接进行通讯
fd_accept = accept(fd_socket,NULL,NULL);
if(fd_accept == -1)
{
perror("accept");
return -1;
}
//获取客户端的请求消息
int len_read = read(fd_accept,buf,1024);
//对buf中的数据进行处理
for(int i = 0;i < len_read;i++)
buf[i] = toupper(buf[i]);
//将处理结果返回给客户端
write(fd_accept,buf,len_read);
//关闭本次连接
close(fd_accept);
}
close(fd_socket);
return 0;
}
----------------------------------------------------------------
/*client.c*/
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
int main(int argc,char *argv[]){
char msg[1024]="hello kitty!\n";
char buf[1024]= {0};
struct sockaddr_in clie;
//创建一个通讯端点
int fd_socket = socket(AF_INET,SOCK_STREAM,0);
if(fd_socket == -1){
perror("socket");
return -1;
}
//使用的地址家族
clie.sin_family = AF_INET;
//端口号
clie.sin_port = htons(6666);
//ip地址
inet_pton(AF_INET,argv[1],&(clie.sin_addr));
//向服务器发起连接,需要知道服务器的地址和端口
int fd_connect = connect(fd_socket,(struct sockaddr *)&clie,sizeof(clie));
if(fd_connect == -1){
perror("connect");
return -1;
}
//向服务器发送消息
write(fd_socket,msg,strlen(msg));
//阻塞等待服务器的响应消息
int len_read = read(fd_socket,buf,1024);
//将服务器的相应消息处理
write(1,buf,len_read);
//关闭连接
close(fd_connect);
return 0;
}