网络变成首先要注意IP和端口的转换,现在电脑基本上是主机字节序,存储按照小端方式,而在网络中传输统一使用大端方式,所以网络变成首先要注意字节序的转换。
一个常用的ip转换程序的实现:
#include
#include
#include
#include
#define CHIP(ip) \ (ip&0xff)<<24 |\ (ip&(0xff<<8))<<8 |\ (ip&(0xff<<16))>>8|\ (ip&(0xff<<24))>>24 int main(int argc,char *argv[]) { char buf[100]=""; int ip[4]={0}; int oldip,newip; scanf("%s",buf); sscanf(buf,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]); //格式化输入,注意去地址符号 printf("%d %d %d %d\n",ip[0],ip[1],ip[2],ip[3]); oldip=(ip[3]<<24)|(ip[2]<<16)|(ip[1]<<8)|ip[0]; printf("%x\n",oldip); // newip=(ip[0]<<24)|(ip[1]<<16)|(ip[2]<<8)|ip[3]; newip=CHIP(oldip);//在计算机中按照十六进制存储的 printf("%x\n",newip); //printf("%d %d %d %d \n",a[0],a[1],a[2],a[3]); memset(buf,0,100); int i; for(i=0;i<4;i++)//将大端模式的IP转换为十进制 好像有BUG { buf[i]=((unsigned int)(newip&((unsigned int)0xff<<8*i))>>8*i); } fprintf(stdout,"%d.%d.%d.%d\n",buf[3],buf[2],buf[1],buf[0]); return 0; }
在网络传输 规定使用大端模式发送,小端模式转大端模式 可以使用这种宏定义
例如小端模式下十六进制的IP为 64 01 a8 c0 //192.168.1.100
#define CHIP(ip) \
(ip&0xff)<<24 | \
(ip&(0xff<<8))<<8 | \
(ip&(0xff<<16))>>8 | \
(ip&(0xff<<24))>>24
转化后的大端模式为:c0 a8 01 64
套接口的概念:
模式 IP:port
套接口,也叫“套接字”。是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户。它是网络进程的ID。网络通信,归根到底还是进程间的通信(不同计算机上的进程间通信)。在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。两个进程通信时,首先要确定各自所在的网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中的哪一个进程进行通信,因此套接口中还需要包括其他的信息,也就是端口号(PORT)。在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一一对应关系。所以,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程。
端口号的概念:
在网络技术中,端口大致有两种意思:一是物理意义上的端口,如集线器、交换机、路由器等用于连接其他网络设备的接口。二是指TCP/IP协议中的端口,端口号的范围从0~65535,一类是由互联网指派名字和号码公司ICANN负责分配给一些常用的应用程序固定使用的“周知的端口”,其值一般为0~1023.例如http的端口号是80,ftp为21,ssh为22,telnet为23等。还有一类是用户自己定义的,通常是大于1024的整型值。
socket概念
Linux中的网络编程是通过socket接口来进行的。socket是一种特殊的I/O接口,它也是一种文件描述符。它是一种常用的进程之间通信机制,通过它不仅能实现本地机器上的进程之间的通信,而且通过网络能够在不同机器上的进程之间进行通信。
每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket来实现的;
socket类型
(1)流式socket(SOCK_STREAM)用于TCP通信
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性。
(2)数据报socket(SOCK_DGRAM)用于UDP通信
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP。
(3)原始socket(SOCK_RAW)用于新的网络协议实现的测试等
原始套接字允许对底层协议如IP或ICMP进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。
头文件
Struct sockddr _in
{
Sa_family_t Sin_family;//存储IPV4格式,见man socket
In_port_t sin_port; //存储端口号
Struct in_addr sin_addr;//IP结构体
};
Struct in_addr
{
In_addr_t s_addr;// 存储IP
};
Typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family //拼接成sin_family
sa_family:AF_INET IPv4协议 AF_INET6 IPv6协议
常用的IP和端口转换函数
如果称某个系统所采用的字节序为主机字节序,则它可能是小端模式的,也可能是大端模式的。而端口号和IP地址都是以网络字节序存储的,不是主机字节序,网络字节序都是大端模式。要把主机字节序和网络字节序相互对应起来,需要对这两个字节存储优先顺序进行相互转化。这里用到四个函数:主机转网络序
htons(),ntohs(),htonl()和ntohl().
这四个地址分别实现网络字节序和主机字节序的转化,这里的h代表host,n代表network,s代表short,l代表long。通常16位的IP端口号用s代表,而IP地址用l来代表。
#include
uint16_t htons(uint_16 hostshort) 一个短整形数 uint16_t ntohs(uint_16 hostshort)
IPv4的函数原型:
#include
#include
#include
int inet_aton(const char *straddr, struct in_addr *addrptr); //点十进制的IP转化为网络字节序。并保存在在IP结构体
char *inet_ntoa(struct in_addr inaddr);//把网络字节序转化了点十进制IP sockaddr.sin_addr
in_addr_t inet_addr(const char *straddr); //较为常用 将十进制数IP转化为sockaddr.sin_addr.s_addr
函数inet_aton():将点分十进制数的IP地址转换成为网络字节序的32位二进制数值。
参数straddr:存放输入的点分十进制数IP地址字符串。
参数addrptr:传出参数,保存网络字节序的32位二进制数值。
函数inet_ntoa():将网络字节序的32位二进制数值转换为点分十进制的IP地址。
函数inet_addr():功能与inet_aton相同,但是结果传递的方式不同。inet_addr()若成功则返回32位二进制的网络字节序地址。
#include
#include
#include
#includ