什么是socket
socket可以看成是用户进程与内核网络协议栈的编程接口。不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信。
socket编程基础
基础知识之大小端和字节序
大端:数据低位在地址高位
小端:数据低位在地址低位
如0x12345678
按地址从低到高排布:
小端:0x78 0x56 0x34 0x12
大端:0x12 0x34 0x56 0x78
主机字节序取决于不同的平台架构,如x86为小端。
网络字节序人为规定为大端。
套接字地址数据结构
IPv4套接口地址结构
/*/usr/include/netinet/in.h*/
struct sockaddr_in
{
__SOCKADDR_COMMON(sin_);
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[sizeof(struct sockaddr)-
__SOCKADDR_COMMON_SIZE-
sizeof(in_port_t)-
sizeof(struct in_addr)];
}
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
/*__SOCKADDR_COMMON的定义位于/usr/include/i386-linux-gnu/bits/sockaddr.h*/
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix)\
sa_family_t sa_prefix##family
- sin_family指定地址族,此处设定为AF_INET
- sin_port指定端口
- sin_addr ipv4地址
通用地址结构
/*/usr/include/i386-linux-gnu/bits/socket.h*/
struct sockaddr
{
__SOCKADDR_COMMON(sa_);
char sa_data[14];
};
- sa_family:指定地址族
- sa_data:由sin_family决定其内容和形式
一般使用来说,先填充ipv4地址结构sockaddr_in相关数据,然后将其强制转为通用地址结构sockaddr。
字节序转换函数
- uint32_t htonl(uint32_t hostlong):将主机字节序hostlong转为网络字节序。
- uint16_t htons(uint16_t hostshort):将主机字节序hostshort转为网络字节序。
- uint32_t ntohl(uint32_t netlong):将网络字节序netlong转为主机字节序。
- uint16_t ntohs(uint16_t netshort):将网络字节序netshort转为主机字节序。
- 注意 h:host;n:network;s:short;l:long
地址转换函数
- int inet_aton(const char* cp,struct in_addr* inp)/*点分十进制转为32位整数(网络字节序)转换结果存储于inp参数中*/
- in_addr_t inet_addr(const char* cp)/*点分十进制转为32位整数(网络字节序)*/
- char* inet_ntoa(struct in_addr in)/*地址结构转换为点分十进制ip地址(字符串)*/
测试程序
#makefile
.PHONY:clean
CC = gcc -std=c99
CFLAGS = -Wall -g
OBJS =test.o
BIN =test
$(BIN):$(OBJS)
$(CC) $(CFLAGS) $^ -o $@
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf $(BIN) $(OBJS)
/*测试程序*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char* argv[])
{
char* ip = "10.3.8.211";
struct in_addr in;
inet_aton(ip,&in);
/*output = 3540517642*/
printf("[%u]\n",in.s_addr);
in.s_addr = 3540517642u;
/*output 10.3.8.211*/
printf("[%s]\n",inet_ntoa(in));
return 0;
}
套接字类型
- 流式套接字(SOCK_STREAM):提供面向连接的,可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收。
- 数据报套接字(SOCK_DGRAM):提供无连接服务。不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
- 原始套接字(SOCK_RAW)