在年轻人的颈项上,没有什么东西能比事业心这颗灿烂的宝珠更迷人的了。 —— 哈菲兹
初识socket网络编程,这篇文章先介绍一下简单的IPC通信
IPC通信即为本地通信,是本机进程之间的通信。
先说一下本地通信所需要的结构体
#include <un.h>
struct sockaddr_un{
int sun_family; //用于指定协议族,和socket()的第一个参数一致。
char sun_path[]; //用来存socket文件名(作为交互媒介)
}
struct sockaddr //用于做函数参数,不负责存储数据
然后是基本的函数
Socket
int socket(int domain, int type, int protocol);
socket函数是通信中最基本的函数,用来创建一个套接口。
参数domain:选择协议族
备选用宏
本地通信 | AF_UNIX/AF_LOCAL/AF_FILE |
---|---|
网络通信 | AF_INET/AF_INET6 |
参数type:选择通信类型
备选用宏
SOCK_STREAM | 字节流,用于TCP |
---|---|
SOCK_DFRAM | 数据报流,用于UDP |
SOCK_DGRAM | 用于本地通信 |
参数protocol:由于前面两个参数已经确定了通信协议,因此这个参数一般不需要,为0。
成功返回socket描述符,失败则返回-1
Bind
int bind(int sockfd,struct sockaddr* myaddr,addr,socklen_t size)
bind函数用于绑定socket描述符与套接字(IP和端口号),用于服务器端
参数sockfd:创建socket函数返回的socket描述符
参数myaddr是struct sockaddr*类型的,是通信地址的指针,即指向我们存储的套接字socket的信息。
参数size:通信地址的大小
Connect
int connect(int sockfd,struct sockaddr* myaddr,addr,socklen_t size)
connect函数与bind函数一模一样,用于客户端。这里不赘述
对于本地socket通信,需要的结构体和函数就这么些,然后说一说我们的编程步骤吧
服务器端:
1.调用socket(),用来创建一个socket描述符
2.准备通信地址(三个结构体),进行数据交互。
3.绑定通信地址和socket描述符,函数bind( )。
4.读写描述符,和读写文件描述符方式一样,read/write
5.函数close:关闭socket描述符
客户端:
除了bind函数换成connect函数,其余一样。
下面给出一个简单的代码:
服务器端
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: server.c
* Description: This file
*
* Version: 1.0.0(06/05/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/05/2017 07:13:26 AM"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
int main(int argc, char **argv)
{
int fd = socket(AF_UNIX, SOCK_DGRAM, 0); //1
if (fd == -1)
{
perror("socket");
exit(-1);
}
struct sockaddr_un addr; //2
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "a.sock");
int res = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); //3 注意第二个参数的类型
if (res == -1)
{
perror("bind");
exit(-1);
}
printf("bind ok!\n");
char buf[100] = {};
res = read(fd, buf, sizeof(buf)); //4
printf("读到了%d个字节,内容为:%s\n", res, buf);
close(fd); //5
return 0;
}
客户端
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: client.c
* Description: This file
*
* Version: 1.0.0(06/05/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/05/2017 07:22:49 AM"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
int main(int argc, char **argv)
{
int fd = socket(AF_UNIX, SOCK_DGRAM, 0); //1
if (fd == -1)
{
perror("socket");
exit(-1);
}
struct sockaddr_un addr; //2
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "a.sock");
int res = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); //3
if (res == -1)
{
perror("connect");
exit(-1);
}
printf("connect ok!\n");
write(fd, "hello", 5); //4
close(fd); //5
return 0;
}
下面是运行的一个结果
服务器端执行
可以看见,bind成功之后等待客户端的连接,并且生成了a.sock交互文件,这个文件的大小为0,可见并不是真实存在。
客户端
这时服务器端可收到客户端发来的消息
到这里,简单的本机通信就算完成了,按着步骤,即套路来写是很简单的。下面文章将会学习比较难的网络通信了。