Linux网络编程基础API
2017-03-17 20:06
471 查看
一、套接字的地址结构
1)IPv4套接字:
2)IPv6:
二、IP地址转换函数
由于人们喜欢用可读性好的字符串来表示IP地址,用点分十进制字符串表示IPv4,用十六进制字符串表示IPv6地址。但在网络中应把它们转化为二进制使用。而记录日志相反。以下三个函数可用于相互之间的转换:
下面两个更新的函数对IPv4和IPv6都可使用:
上面的af指定地址族,dst指定结果存储的内存,cnt指定目标存储单元的大小。
下面两个宏定义了cnt的大小:
三、创建socket
UNIX/Linux中:所有东西都是文件。socket也不例外,它就是可读、可写、可控制、可关闭的文件描述符。下面socket系统调用创建一个socket:
成功时创建一个文件描述符,失败返回-1,设置为errno。
四、命名socket:讲一个socket与socket地址绑定成为给socket命名。
bind成功时返回0,失败时返回-1,并设置errno。其中两个常见的errno为:
*EACCES,被绑定的地址受保护,仅超级用户能够访问。如普通用户将socket绑定到知名服务端口(0~1023)时,返回EACCES。
*EADDRINUSE,被绑定的地址正在使用中。比如把socket绑定到一个处于TIME_WAIT状态的socket。
五、监听socket
调用一个监听队列存放待处理的客户连接:
六、接受连接
七、发起连接
八、关闭连接
关闭一个连接实际上就是关闭该连接对应的socket。
九、数据读写
对文件的读写操作read和write同样适用于socket。但socket的读写增加了对数据控制。用于TCP流数据读写的系统调用是:
ssize_t为:sign size_t类型的,可以被执行读写操作的数据块的大小。
几个重要的flags参数的可选值:
MSG_OOB:发送或接收紧急数据(提供带外数据的发送和接收)。
下面两个代码一个为发送带外数据,一个为接收带外数据。
1)IPv4套接字:
#include<netinet/in.h> struct sockaddr_in { sa_family_t sin_family; //地址族,AF_INET u_int16_t sin_port; //端口号,用网络字节表示 Struct in_addr sin_addr; //IPv4地址结构,如下 }; struct in_addr { u_int32_t s_addr; //IPv4地址,用网络字节序表示 };
2)IPv6:
struct sockaddr_in6 { sa_family_t sin6_family; //地址族,AF_INET6 u_int16 sin6_port; //端口号,用网络字节表示 u_int32_t sin6_flowinfo; //信息流,应设置为0 struct in6_addr sin6_addr; //IPv6地质结构体,如下 u_int32_t sin6_scope_id; //scope ID,现处实验阶段 }; struct in6_addr { unsigned cahr sa_addr[16]; //IPv6地址,用网络字节序表示 };
二、IP地址转换函数
由于人们喜欢用可读性好的字符串来表示IP地址,用点分十进制字符串表示IPv4,用十六进制字符串表示IPv6地址。但在网络中应把它们转化为二进制使用。而记录日志相反。以下三个函数可用于相互之间的转换:
#include<arpa/inet.h> in_addr_t inet_addr(const char* strptr); //IPv4地址字符串->二进制 int inet_aton(const char* cp, struct in_addr* inp); //同上,结果存于inp指向的地址结构中 cahr* inet_ntoa(struct in_addr in); //网络字节->点分十进制(内部用静态变量存储转化结果,因此具有不可重入性)
下面两个更新的函数对IPv4和IPv6都可使用:
#include<arpa/inet.h> int inet_pton(int af, const char* src, void* dst); const char* inet_ntop(int af, const void* src, char* dst, socklen_t cnt);
上面的af指定地址族,dst指定结果存储的内存,cnt指定目标存储单元的大小。
下面两个宏定义了cnt的大小:
#include<netinet/in.h> #define INET_ADDRESTRLEN 16 #define INET6_ADDRESTRLEN 46
三、创建socket
UNIX/Linux中:所有东西都是文件。socket也不例外,它就是可读、可写、可控制、可关闭的文件描述符。下面socket系统调用创建一个socket:
#include<sys/types.h> #include<sys/socket.h> int socket(int domain, int type, int protocol); // 协议族 服务类型(流或数) 几乎默认为0
成功时创建一个文件描述符,失败返回-1,设置为errno。
四、命名socket:讲一个socket与socket地址绑定成为给socket命名。
#include<sys/types.h> #include<sys/socket.h> int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
bind成功时返回0,失败时返回-1,并设置errno。其中两个常见的errno为:
*EACCES,被绑定的地址受保护,仅超级用户能够访问。如普通用户将socket绑定到知名服务端口(0~1023)时,返回EACCES。
*EADDRINUSE,被绑定的地址正在使用中。比如把socket绑定到一个处于TIME_WAIT状态的socket。
五、监听socket
调用一个监听队列存放待处理的客户连接:
#include<sys/socket.h> int listen(int sockfd, int backlog); // 监听队列的最大长度(典型参数为5)
六、接受连接
#include<sys/types.h> #include<sys/socket.h> int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen); // 获取被接受连接的远端socket地址 接收地址长度参数
accept只是从监听队列中取出连接,而不论连接处于何种状态,更不关心网络的变化。
七、发起连接
#include<sys/types.h> #include<sys/socket.h> int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
八、关闭连接
关闭一个连接实际上就是关闭该连接对应的socket。
#include<unistd.h> int close(int fd); //fd->待关闭的socket
close系统调用并不非是立即关闭一个连接,而是将fd的引用计数减1,只有当fd的引用计数为0时,才真正关闭连接。 当无论如何都要立即终止连接,可以使用shutdown调用:
#include<sys/socket.h> #int shutdown(int sockfd, int howto);
九、数据读写
对文件的读写操作read和write同样适用于socket。但socket的读写增加了对数据控制。用于TCP流数据读写的系统调用是:
ssize_t为:sign size_t类型的,可以被执行读写操作的数据块的大小。
(1)发送带外数据
#include<sys/types.h> #include<sys/socket.h> // 位置 大小 默认0 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);
几个重要的flags参数的可选值:
MSG_OOB:发送或接收紧急数据(提供带外数据的发送和接收)。
下面两个代码一个为发送带外数据,一个为接收带外数据。
#include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<assert.h> #include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> int main(int argc, char* argv[]) { int t = 1; if(argc<=2) { printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } const char< c758 /span>* ip = argv[1]; int port = atoi(argv[2]); struct sockaddr_in server_address; bzero(&server_address, sizeof(server_address)); server_address.sin_family = AF_INET; inet_pton(AF_INET, ip, &server_address.sin_addr); server_address.sin_port = htons(port); int sockfd = socket(PF_INET, SOCK_STREAM,0); assert(sockfd >=0); if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0) { printf("connection failed\n"); } else { const char* oob_data = "wer"; const char* normal_data = "987"; send(sockfd, normal_data,strlen(normal_data), 0); send(sockfd, oob_data,strlen(oob_data),MSG_OOB); send(sockfd, normal_data,strlen(normal_data), 0); scanf("%d\n", t); } close(sockfd); return 0; }
(2)接收带外数据
#include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<assert.h> #include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<errno.h> #define BUF_SIZE 1024 int main(int argc, char* argv[]) { if(argc<=2) { printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } const char* ip = argv[1]; int port = atoi(argv[2]); struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); int sock = socket(PF_INET,SOCK_STREAM,0); assert(sock>=0); int ret = bind(sock,(struct sockaddr*)&address, sizeof(address)); assert(ret !=-1); ret = listen(sock,5); assert(ret !=-1); struct sockaddr_in client; socklen_t client_addrlength = sizeof(client); int connfd = accept(sock, (struct sockaddr*)&client,&client_addrlength); if(connfd<0) { printf("errno is: %d\n",errno); } else { char buffer[BUF_SIZE]; memset(buffer,'\0',BUF_SIZE); ret = recv(connfd, buffer, BUF_SIZE-1, 0); printf("got %d bytes of normal data '%s'\n", ret, buffer); memset(buffer, '\0',BUF_SIZE); ret = recv(connfd,buffer,BUF_SIZE-1,MSG_OOB); printf("got %d bytes of oob data '%s'\n", ret, buffer); memset(buffer, '\0',BUF_SIZE); ret = recv(connfd, buffer, BUF_SIZE-1, 0); printf("got %d bytes of normal data '%s'\n", ret, buffer); close(connfd); } close(sock); return 0; }
相关文章推荐
- 《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(2)
- 5 Linux网络编程基础API
- 《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(3)
- Linux 高性能服务器编程——Linux网络编程基础API
- Linux高性能server编程——Linux网络基础API及应用
- 第二篇 深入解析高性能服务器编程 第5章 Linux 网络编程基础API
- socket 基础(Linux网络编程基础API)
- Linux下的网络编程API基础
- Linux 高性能服务器编程——Linux网络编程基础API
- 《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(1)
- Linux网络编程基础API(多线程实现)
- 《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(5)
- Linux 高性能服务器编程——Linux网络编程基础API
- 服务器编程入门(4)Linux网络编程基础API
- linux网络编程基础API(二)
- 《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(4)
- linux网络编程之TCP/IP基础(五):分析一帧基于UDP的TFTP协议帧
- 13、linux网络编程基础
- linux 网络编程基础
- 【Linux网络编程笔记】TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法—基础知识篇