IP地址的定义
IP地址由两部分组成 主机号和网络号两部分.同时 IP 地址由 32 为整数表示. TCP/IP通信要求将这样的IP地址分配给每个参与通信的主机. 为了方便用户的认识, 通常将 IP地址以 8 个比特位为一组组成一个十进制数字,总共分成 4 组, 每组以 . 的形式将其隔开.
在数据帧的头部有两个 IP 地址, 一个是源 IP 地址, 表示数据帧来自哪里, 还有一个目标 IP 地址, 用来表示数据包想要取得主机. 不同的局域网之间的两台主机要想实现通信, 必须先找到目标主机对应的局域网之后才能找到目标主句.
IP地址的分类
IP地址可以分为四大类, A类, B类, C类, D类. 通过 IP地址中从第一位到第四位的比特列对其网络表示和主机表示进行区分
1. A类地址
A 类 IP 地址首部以”0”开头的地址. 从第一位到第八位是它的网络标号. 即 0.0.0.0 ~ 127.0.0.0 是 A 类地址. A 类地址的后 24 位相当于主机标示.
2. B类地址
B 类 IP 地址的前两位是 “10”的地址, 第一位到第十六为是网络号,即 128.0.0.0 ~ 191.255.0.0是 B类地址. B 类地址后面的十六位表示主机标示
3. C类地址
C 类地址是以 110 开头, 从第一位到第二十四位是它的网络标示. 即 192.0.0.0 ~ 223.255.255.0 是C类的网络地址. C类地址的后 8 位表示主机号
4. D类地址
D类地址以1110开头, 从第一位到第三十二位都是网络标示. 224.0.0.0 ~ 223.255.255.255 表示的是网络标示. 没有主机号, 通常用于多播.
端口号
端口号是定义在传输层的, 用来表示同一台计算机中正在通信的不同应用进程.一个端口号加一个IP地址就可以确定网络上的某台主机上的一个进程. 一个端口号只能由一个进程占有. 两个通信的主句之间进程号可能重复, 但是端口号不可能重复. 一个进程可以绑定多个端口号, 但是一个端口号不能被多个进程绑定
源端口号和目标端口号
用来表示数据是由谁发的, 这个数据要发给谁
UDP
面向无连接, 无流量控制, 无差错检验功能. 不可靠.并且是面向数据报的一种传输层协议, 将部分控制转移给应用进程, 自己只提供传输层的机本功能.
TCP
具有丢包时的重发功能, 面向有连接的协议, 可以控制通信流量的浪费.是一种可靠的面向数据字节流的传输层协议
网络字节序
发送主机通常将发送缓冲区的数据按照从低到高的顺序发出;
接收方也将接收到的数据字节一次保存在缓冲区, 也是按照内存地址从低到高的顺序进行保存
即网络字节序的规定是先发的数据是低地址, 后发的数据是高地址
TCP/IP规定网络数据流采用大端字节序, 即低地址, 高字节
如果某台主机是小端机器, 在发送数据的时候必须转换为大端才能进行发送.
UDP相关代码
//udp_client.c
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("输入错误\n");
exit(1);
}
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
perror("socket\n");
exit(1);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons(atoi(argv[2]));
char buf[1024];
struct sockaddr_in peer;
while(1)
{
socklen_t len = sizeof(peer);
printf("Please enter#");
fflush(stdout);
ssize_t s = read(0, buf, sizeof(buf));
if(s > 0)
{
buf[s -1] = 0;
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&server, sizeof(server));
ssize_t _s = recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&peer, &len);
if(_s > 0)
{
buf[_s] = 0;
printf("server echo# %s\n", buf);
}
}
}
return 0;
}
//udp_server.c
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
//127.12.12 888
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("输入错误\n");
exit(1);
}
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(atoi(argv[2]));
local.sin_addr.s_addr = inet_addr(argv[1]);
if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)
{
perror("sock\n");
exit(1);
}
char buf[1024];
struct sockaddr_in client;
while(1)
{
socklen_t len = sizeof(client);
ssize_t s = recvfrom(sock, &buf, sizeof(buf) - 1, 0, (struct sockaddr*)&client, &len);
if(s > 0)
{
buf[s] = 0;
printf("[%s: %d]: %s\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port), buf);
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&client, sizeof(client));
}
}
return 0;
}