一、本机通信分类
1、AF_INET 与 AF_UNIX
int socket(int domain, int type, int protocol);
;
- 其中
domain
:
- AF_UNIX(本机通信)
- AF_INET(TCP/IP – IPv4)
- AF_INET6(TCP/IP – IPv6)
- 其中 “type”参数指的是套接字类型,常用的类型有:
- SOCK_STREAM(TCP流)
- SOCK_DGRAM(UDP数据报)
- SOCK_RAW(原始套接字)
2、区别
- 两者路径不同;一个通过本地IPC 通信;一个通过完整网络通信;
- bind()的地址结构分别为sockaddr_in(制定IP端口)和sockaddr_un(指定路径名)
- AF_INET需经过多个协议层的编解码,消耗系统cpu,并且数据传输需要经过网卡,受到网卡带宽的限制。
AF_UNIX数据到达内核缓冲区后,由内核根据指定路径名找到接收方socket对应的内核缓冲区,直接将数据拷贝过去,不经过协议层编解码,节省系统cpu,并且不经过网卡,因此不受网卡带宽的限制;
- AF_UNIX的传输速率远远大于AF_INET;
- AF_INET不仅可以用作本机的跨进程通信,同样的可以用于不同机器之间的通信,其就是为了在不同机器之间进行网络互联传递数据而生。而AF_UNIX则只能用于本机内进程之间的通信。
二、linux实例
1、unix 域套接字的本地socket 文件通信;
- 服务端;
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
int main (int argc,char *argv[])
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address; /*声明一个UNIX域套接字结构*/
struct sockaddr_un client_address;
int i, bytes;
char ch_send, ch_recv;
unlink ("server_socket"); /*删除原有server_socket对象*/
/*创建 socket, 通信协议为AF_UNIX, SCK_STREAM 数据方式*/
server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
/*配置服务器信息(通信协议)*/
server_address.sun_family = AF_UNIX;
/*配置服务器信息(socket 对象)*/
strcpy (server_address.sun_path,"server_socket");
/*配置服务器信息(服务器地址长度)*/
server_len =sizeof (server_address);
/*绑定 socket 对象*/
bind (server_sockfd, (struct sockaddr *)&server_address, server_len);
/*监听网络,队列数为5*/
listen (server_sockfd, 5);
printf ("Server is waiting for client connect...\n");
client_len =sizeof (client_address);
/*接受客户端请求; 第2个参数用来存储客户端地址; 第3个参数用来存储客户端地址的大小*/
/*建立(返回)一个到客户端的文件描述符,用以对客户端的读写操作*/
client_sockfd = accept (server_sockfd, (struct sockaddr *)&server_address, (socklen_t *)&client_len);
if (client_sockfd == -1) {
perror ("accept");
exit (EXIT_FAILURE);
}
printf ("The server is waiting for client data...\n");
for (i = 0, ch_send ='1'; i < 5; i++, ch_send++) {
if ((bytes = read (client_sockfd, &ch_recv, 1)) == -1) {
perror ("read");
exit (EXIT_FAILURE);
}
printf ("The character receiver from client is %c\n", ch_recv);
sleep (1);
if ((bytes = write (client_sockfd, &ch_send, 1)) == -1) {
perror ("read");
exit (EXIT_FAILURE);
}
}
close (client_sockfd);
unlink ("server socket");
}
- 客户端
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
int main (int argc,char *argv[])
{
struct sockaddr_un address;
int sockfd;
int len;
int i, bytes;
int result;
char ch_recv, ch_send;
/*创建socket,AF_UNIX通信协议,SOCK_STREAM数据方式*/
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror ("socket");
exit (EXIT_FAILURE);
}
address.sun_family = AF_UNIX;
strcpy (address.sun_path,"server_socket");
len =sizeof (address);
/*向服务器发送连接请求*/
result = connect (sockfd, (struct sockaddr *)&address, len);
if (result == -1) {
printf ("ensure the server is up\n");
perror ("connect");
exit (EXIT_FAILURE);
}
for (i = 0, ch_send ='A'; i < 5; i++, ch_send++) {
if ((bytes = write(sockfd, &ch_send, 1)) == -1) {/*发消息给服务器*/
perror ("write");
exit (EXIT_FAILURE);
}
sleep (2); /*休息二秒钟再发一次*/
if ((bytes = read (sockfd, &ch_recv, 1)) == -1) {/*接收消息*/
perror ("read");
exit (EXIT_FAILURE);
}
printf ("receive from server data is %c\n", ch_recv);
}
close (sockfd);
return (0);
}
2、socket 四元组通信;
- 服务端
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib,"Ws2_32.lib")
#include <memory.h>
#define BUF_SIZE 4096
#define QUEUE_SIZE 5
DWORD WINAPI ThreadProcServerConmunicate(
_In_ LPVOID lpParameter
) {
SOCKET * psc = (SOCKET *)lpParameter;
int receByt = 0;
while (1)
{
char buf[BUF_SIZE];
receByt = recv(*psc, buf, BUF_SIZE, 0);
buf[receByt] = '\0';
if (receByt>0)
{
printf("%u : 接收的消息是:%s\n", *psc, buf);
}
else
{
printf("接收消息结束!");
break;
}
}
int ic = closesocket(*psc);
free(psc);
return 0;
}
int main() {
WSADATA wsd;
WSAStartup(MAKEWORD(2, 0), &wsd);
SOCKET s = NULL;
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch, 0, sizeof(ch));
ch.sin_family = AF_INET;
ch.sin_addr.s_addr = INADDR_ANY;
ch.sin_port = htons(5174);
int b = bind(s, (struct sockaddr *) &ch, sizeof(ch));
int l = listen(s, QUEUE_SIZE);
printf("正在监听本机的5174端口\n");
while (1) {
SOCKET * psc = (SOCKET *)malloc(sizeof(SOCKET));
*psc = accept(s, 0, 0);
printf("一个客户端已经连接到本机的5174端口,SOCKET是 : %u \n", *psc);
CreateThread(NULL,
0,
&ThreadProcServerConmunicate,
psc,
0,
NULL
);
}
int is = closesocket(s);
WSACleanup();
return 0;
}
- 客户端
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib,"Ws2_32.lib")
#include <memory.h>
#define BUF_SIZE 4096
void main()
{
WSADATA wsd;
WSAStartup(MAKEWORD(2, 0), &wsd);
SOCKET s = NULL;
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch, 0, sizeof(ch));
ch.sin_family = AF_INET;
ch.sin_addr.s_addr = inet_addr("127.0.0.1");
ch.sin_port = htons(5174);
int c = connect(s, (struct sockaddr *) &ch, sizeof(ch));
printf("已经连接到服务器的5174端口,现在可以向服务器发送消息了!\n");
char info[1024], buf[BUF_SIZE];
while (1)
{
gets(info);
if (info[0] == '\0')
break;
strcpy(buf, info);
int nsend = send(s, buf, strlen(buf), 0);
Sleep(500);
}
int ic = closesocket(s);
WSACleanup();
return 0;
参考
https://blog.csdn.net/sandware/article/details/40923491