1、创建socket
#include <sys/types.h>        
#include <sys/socket.h>     

int socket(int domain, int type, int protocol);

功能:创建socket描述符,可以把socket当作文件来看待,发送数据就是写文件,接收数据就是读文件
domain:地址文件
    AF_UNIX/AF_LOCAL/AF_FILE   本地通信(进程间通信)
    AF_INET       基于32位IP地址通信,IPv4
    AF_INET6     基于128位IP地址通信,IPv6
type:通信协议
    SOCK_STREAM  数据流协议  TCP
    SOCK_DGRAM  数据报协议   UDP
protocol:特别通信协议,给0即可
返回值:socket描述符,类似文件描述符

2、通信地址
注意:函数接口定义的是sockaddr,而实际提供的是sockaddr_un或sockaddr_in

struct sockaddr
{
          sa_family_t sa_family;
          char        sa_data[14];
};

struct sockaddr_un         (本地)
{
          __SOCKADDR_COMMON (sun_);  //地址类型 参看domain
         char sun_path[108];                              //socket文件的路径
};

struct sockaddr_in         (tcp)         
{
         __SOCKADDR_COMMON (sin_);
         in_port_t sin_port;                                 //端口号   大端字节序
         struct in_addr sin_addr;                        //ip地址   大端4字节整数
};
struct in_addr
{
         in_addr_t s_addr;
};

3、绑定(套接字描述符)
socket描述符与物理通信载体(网卡或socket文件)绑定在一起

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:socket描述符:
addr:通信自己地址结构体,实际给的是sockaddr_un或sockaddr_in,需要强制类型转换
addrlen:通信地址结构体类型的字节数,使用sizeof计算
成功返回0,失败返回-1

例:

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

4、连接

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:socket描述符
addr:通信目标地址
addrlen:通信地址结构体类型的字节数,使用sizeof计算
返回值:在不同的编程模型下返回值意义不同,在本地通信,成功返回0 失败返回-1

5、数据接收与发送:  

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

recv/send与read/write功能一样,flags多了是否阻塞的功能(0阻塞,1不阻塞)

6、关闭套接字:close
如果是网络通信,端口号不会立即回收,大概会占用3分钟左右

7、字节序的转换
#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);
功能:把32位的本机字节序转换成32位的网络字节序

uint16_t htons(uint16_t hostshort);
功能:把16位的本机字节序转换成16位的网络字节序

uint32_t ntohl(uint32_t netlong);
功能:把32位的网络字节序转换成32位的本机字节序

uint16_t ntohs(uint16_t netshort);
功能:把16位的网络字节序转换成16位的本机字节序

8、ip地址转换
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>     

int inet_aton(const char *cp, struct in_addr *inp);
功能:把点分十进制的ip地址(字符串)转换成32位的无符号整数,使用结构指针获取

in_addr_t inet_addr(const char *cp);
功能:把点分十进制的ip地址(字符串)转换成32位的无符号整数,使用返回值直接返回

char *inet_ntoa(struct in_addr in);
功能:32位无符号整数表示的ip地址,转换成点分十进制的ip地址(字符串)

9、本地通信编程模型
进程A                                                              进程B
创建套接字(AF_LOCAL)                            创建套接字(AF_LOCAL)
准备地址(sockaddr_un)                             准备地址(sockaddr_un)
绑定(进程A(自己的)socket/地址)           连接(connect,连接进程A的地址)
接收数据                                                         发送数据
关闭套接字                                                     关闭套接字
删除socket文件:unlink(SOCK_FILE)

//a.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_FILE	"/tmp/sock"

int main()
{
	// 创建socket
	int sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return -1;
	}

	// 准备地址
	struct sockaddr_un addr = {};
	addr.sun_family = AF_LOCAL;
	strcpy(addr.sun_path,SOCK_FILE);

	// 绑定
	if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
	{
		perror("bind");
		return -1;
	}

	char buf[1024] = {};
	for(;;)
	{
		int ret = read(sockfd,buf,sizeof(buf));
		if(0 > ret)
		{
			perror("read");
			return -1;
		}
		printf("read:%s\n",buf);
		if(0 == strcmp("quit",buf))
		{
			printf("通信完成!\n");
			break;
		}
	}

	// 关闭socket
	close(sockfd);
	// 删除socket文件
	unlink(SOCK_FILE);
}
//b.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_FILE	"/tmp/sock"

int main()
{
	// 创建socket
	int sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return -1;
	}

	// 准备地址
	struct sockaddr_un addr = {};
	addr.sun_family = AF_LOCAL;
	strcpy(addr.sun_path,SOCK_FILE);

	// 
	if(connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
	{
		perror("connect");
		return -1;
	}

	char buf[1024] = {};
	for(;;)
	{
		printf(">");
		gets(buf);
		int ret = write(sockfd,buf,strlen(buf)+1);
		if(0 > ret)
		{
			perror("write");
			return -1;
		}
		if(0 == strcmp("quit",buf))
		{
			printf("通信完成!\n");
			break;
		}
	}

	// 关闭socket
	close(sockfd);
}