linux IPC socket
套接字是通讯端点的抽象
创建一个套接字
#include <sys/types.h>
#include <sys/socket.h> int socket(int domain, int type, int protocol);
返回值:成功文件(套接字)描述符,失败-1
domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。
协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
protocal:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等
它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
套接字通信是双向的。可以禁止一个套接字的I/O
#include <sys/socket.h> int shutdown(int sockfd, int how);
返回值:成功0,出错-
sockfd:套接字的描述符
how:三种SHUT_RD()关闭sockfd上的读功能
SHUT_WR()关闭sockfd上的写功能
SHUT_RDWR()关闭sockfd的读写功能
用来在处理器字节序和网络字节序之间实施转换的函数
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong);
返回值:以网络字节序表示的32位整数
uint16_t htons(uint16_t hostshort);
返回值:以网络字节序表示的16位整数
uint32_t ntohl(uint32_t netlong);
返回值:以主机字节序表示的32位整数
uint16_t ntohs(uint16_t netshort);
返回值:以主机字节序表示的16位整数
h表示主机字节序,n表示网络字节序,l表示长整型,s表示短整型
打印出能被人理解而不是计算机所理解的地址格式。同时支持IPv4和IPv6地址
#include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
返回值:成功地址字符串指针,出错NULL
af:地址簇,仅支持AF_INET和AF_INET6
src:来源地址结构指针
dst:接收转换后的字符串
size:保存文本字符串的缓冲区大小 int inet_pton(int af, const char *src, void *dst);
返回值:成功1,格式无效0,出错-
af:地址簇,仅支持AF_INET和AF_INET6
src:转换的地址字符串
dst:转换后的地址结构指针
这个很常用,所有使用socket都需要用这两个函数转换,p应该是protocol,n应该是net吧。
例子
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h> int main(int argc, char *argv[])
{
char dst[];
int sockfd = socket(AF_INET, SOCK_STREAM, ); struct sockaddr_in serv;
memset(&serv, ,sizeof(struct sockaddr_in)); serv.sin_family = AF_INET;
serv.sin_port = htons(); if((inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr)) == )
printf("inet_pton error\n");
if((inet_ntop(AF_INET, &serv.sin_addr.s_addr, dst, sizeof(dst))) == NULL)
printf("inet_ntop error\n");
printf("dst=%s,sizeof(dst)=%d\n", dst, sizeof(dst)); bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));
listen(sockfd, );
return ;
}
inet_pton
找到给定计算机系统的主机信息
#include <netdb.h> struct hostent *gethostent(void);
返回值:成功返回指针,出错NULL void sethostent(int stayopen);
stayopen:true就是TCP,否则UDP void endhostent(void);
能够采用一套相似的接口来获得网络名字和网络编号
#include <netdb.h> struct netent *getnetbyaddr(uint32_t net, int type);
struct netent *getnetbyname(const char *name);
struct netent *getnetent(void);
返回值:成功返回指针,出错NULL void setnetent(int stayopen);
void endnetent(void);
在协议名字和协议编号之间进行映射
#include <netdb.h> struct protoent *getprottobyname(const char *name);
struct protoent *getprotobynumber(int proto);
struct protoent *getprotoent(void);
返回值:成功返回指针,出错NULL void setprotoent(int stayopen);
void endprotoent(void);
服务是由地址的端口号部分表示的,每个服务由一个唯一的众所周知的端口号来支持。可以使用getservbyname将一个服务名映射到一个端口号,使用函数getservbyport将一个端口号映射到一个服务名,使用函数getservent顺序扫描服务数据库。
#include <netdb.h> struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
struct servent *getservent(void);
返回值:成功返回指针,出错NULL void setservent(int stayopen);
void endservent(void);
将一个主机和一个服务名映射到一个地址
#include <sys/socket.h>
#include <netdb.h> int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
返回值:成功0,出错非0错误码
node:向一个主机名(域名)或者地址串(IPv4的点分十进制串或者IPv6的16进制串)。
service:指向一个服务名或者10进制端口号数串。
hints:可以是一个空指针,也可以是一个指向某个addrinfo结构的指针
res:指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo结构链表 void freeaddrinfo(struct addrinfo *res);
addrinfo结构体
struct addrinfo
{
int ai_flags;
int ai_family; //AF_INET,AF_INET6,UNIX etc
int ai_socktype; //STREAM,DATAGRAM,RAW
int ai_protocol; //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc
size_t ai_addrlen;//length of ai_addr
char* ai_canonname; //full hostname
struct sockaddr* ai_addr; //addr of host
struct addrinfo* ai_next;
}
错误码需要调用函数来转换成错误消息
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h> const char *gai_strerror(int errcode);
将一个地址转换成一个额主机名和一个服务名
#include <sys/socke.h>
#include <netdb.h> int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);
返回值:成功0,出错非0值
sa:指向包含协议地址的套接口地址结构,它将会被转换成可读的字符串,
salen:结构的长度,这个结构长度通常由accept、recvfrom、getsockname、getpeername
host:主机字符串
hostlen:长度
serv:服务器字符串
servlen:长度
flags:标志位可以有多个用与或
sockaddr结构体
16-9.c
#include "apue.h"
#if defined(SOLARIS)
#include <netinet/in.h>
#endif
#include <netdb.h>
#include <arpa/inet.h>
#if defined(BSD)
#include <sys/socket.h>
#include <netinet/in.h>
#endif void print_family(struct addrinfo *aip)
{
printf(" family ");
switch(aip->ai_family) {
case AF_INET:
printf("inet");
break;
case AF_INET6:
printf("inet6");
break;
case AF_UNIX:
printf("unix");
break;
case AF_UNSPEC:
printf("unspecified");
break;
default:
printf("unknown");
}
} void print_type(struct addrinfo *aip)
{
printf(" type ");
switch(aip->ai_socktype) {
case SOCK_STREAM:
printf("stream");
break;
case SOCK_DGRAM:
printf("datagram");
break;
case SOCK_SEQPACKET:
printf("seqpacket");
break;
case SOCK_RAW:
printf("raw");
break;
default:
printf("unknown (%d)", aip->ai_socktype);
}
} void print_protocol(struct addrinfo *aip)
{
printf(" protocol ");
switch(aip->ai_protocol) {
case :
printf("default");
break;
case IPPROTO_TCP:
printf("TCP");
break;
case IPPROTO_UDP:
printf("UDP");
break;
case IPPROTO_RAW:
printf("raw");
break;
default:
printf("unknown (%d)", aip->ai_protocol);
}
} void print_flags(struct addrinfo *aip)
{
printf("flags");
if(aip->ai_flags == ) {
printf("");
} else {
if(aip->ai_flags & AI_PASSIVE)
printf(" passive");
if(aip->ai_flags & AI_CANONNAME)
printf(" canon");
if(aip->ai_flags & AI_NUMERICHOST)
printf(" numhost");
if(aip->ai_flags & AI_NUMERICSERV)
printf(" numserv");
if(aip->ai_flags & AI_V4MAPPED)
printf(" v4mapped");
if(aip->ai_flags & AI_ALL)
printf(" all");
}
} int main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
struct sockaddr_in *sinp;
const char *addr;
int err;
char abuf[INET_ADDRSTRLEN]; if(argc != )
err_quit("usage: %s nodename service", argv[]);
hint.ai_flags = AI_CANONNAME;
hint.ai_family = ;
hint.ai_socktype = ;
hint.ai_protocol = ;
hint.ai_addrlen = ;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if((err = getaddrinfo(argv[], argv[], &hint, &ailist)) != )
err_quit("getaddrinfo error %s", gai_strerror(err));
for(aip = ailist; aip != NULL; aip = aip->ai_next) {
print_flags(aip);
print_family(aip);
print_type(aip);
print_protocol(aip);
printf("\n\thost %s", aip->ai_canonname?aip->ai_canonname:"-");
if(aip->ai_family == AF_INET) {
sinp = (struct sockaddr_in *)aip->ai_addr;
addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
printf(" address %s", addr?addr:"unknown");
printf(" port %d", ntohs(sinp->sin_port));
}
printf("\n");
}
exit();
}
getaddrinfo
linux IPC socket的更多相关文章
- Linux IPC socket 广播,组播
getsockopt()/setsockopt() //获得sockfd指向的socket的属性 int getsockopt(int sockfd, int level, int optname, ...
- Linux IPC socket编程基础
头文件 #include<unistd.h> #include <sys/types.h> #include <sys/socket.h> #include< ...
- linux IPC socket(3)server简单写法
写server的一些流程总结 一.向内核申请一个socket TCP形式 sock_fd = socket(AF_INET, SOCK_STREAM, ); UDP形式 sfd = socket(AF ...
- linux IPC socket(2)
使用bind来关联地址和套接字 #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, cons ...
- Linux IPC实践(1) -- 概述
进程的同步与互斥 进程同步: 多个进程需要相互配合共同完成一项任务. 进程互斥: 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥;系统中某些 ...
- linux系统socket通信编程详解函数
linux socket编程之TCP与UDP TCP与UDP区别 TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之 ...
- linux ipc/its
linux进程间双向消息队列 server.c #include <stdio.h> #include <stdlib.h> #include <string.h> ...
- linux中socket的理解
对linux中socket的理解 一.socket 一般来说socket有一个别名也叫做套接字. socket起源于Unix,都可以用“打开open –> 读写write/read –> ...
- linux 客户端 Socket 非阻塞connect编程
开发测试环境:虚拟机CentOS,windows网络调试助手 非阻塞模式有3种用途 1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...
随机推荐
- 推荐五个java基础学习网站,小白必备
不知道去哪找java基础资料?推荐几个学习网站,小白必备 Java经过20多年的发展,仍然是世界上最受欢迎的编程语言之一,有无限多种方法使用Java.拥有庞大的客户群.并且java应用范围很广,基本只 ...
- 【LeetCode 31】下一个排列
题目链接 [题解] 从右往左找第一个下降的位置i(即满足nums[i]<nums[i+1]); 然后在[i+1..len-1]这个区间里面找到一个最大的下标k,使得nums[k]>nums ...
- 微信jssdk安卓机分享QQ好友和QQ空间出现{"errMsg":"shareQQ:fail"}
使用ajax请求appid之类的配置,然后进行wx.config和wx.ready,苹果机上是完全OK的,但是安卓机上十次有九次是失败,只有一次能成功,百度了一下,有人说是参数有空格,有人说是微信bu ...
- sql存储过程循环实现事务
//往一张表中添加数据,获取添加数据生成的ID,再往另一张表中添加多条数据 ALTER PROCEDURE [dbo].[AttendanceCardAndDetail_Add] @SchoolID ...
- Linux下dd和od命令备份查看硬盘mbr,并用vim修改!
主引导记录(Master Boot Record,MBR),位于一个硬盘的0柱面.0盘面.1扇区,共512字节.具体划分依次为:引导代码区440字节.磁盘签名4字节.空白(Ox0000)2字节.MBR ...
- setTag()与getTag()的使用介绍
转载博客:http://www.cnblogs.com/topcoderliu/archive/2011/06/07/2074419.html View中的setTag(Onbect)表示给View添 ...
- 为什么NULL能多次free
void __cdecl _free_base (void * pBlock) { int retval = 0; if (pBlock == NULL) ...
- 前端之间的url 传值
转自:https://www.cnblogs.com/candy-Yao/p/8858166.html
- Linux应急响应基础
文件排查 敏感目录文件分析 tmp目录 命令目录 /usr/bin /usr/sbin 开机启动项 /etc/init.d /etc/init.d是/etc/rc.d/init.d的软链接 文件时间 ...
- Java输入/输出教程
Java输入/输出(I/O)处理从源读取数据并将数据写入目标.通常,读取存储在文件中的数据或使用I/O将数据写入到文件中. java.io和java.nio包中包含处理输入/输出的Java类.java ...