htons、ntohs、htonl和ntohl函数

Linux提供了4个函数来完毕主机字节序和网络字节序之间的转换

#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);

inet_aton、inet_addr和inet_ntoa函数

#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
返回:若字符有效则为1,否则为0
in_addr_t inet_addr(const char *strptr);
返回:若字符串有效则为32位二进制网络字节序地址。否则为INADDR_NONE
char *inet_ntoa(struct in_addr inaddr);
返回:指向一个点分十进制数串的地址

inet_aton将strptr所指向的字符串转换为32网络字节序二进制值,并通过addrptr来存储。成功返回1,失败返回0。inet_addr进行与inet_aton同样的转换,inet_addr不能处理点分十进制字符串255.255.255.255,由于它的二进制值被用来仅仅是函数返回失败,可是,有的编译器的INADDR_NONE不一定是这样的。

注意,这3个函数操作的in_addr结构是网络字节序的。进行网络二进制和点分字符串转换最好用inet_pton和inet_ntop函数,它们是与协议无关的。

inet_pton和inet_ntop函数

#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
返回:成功为1。输入不是有效表达式返回0。出错为-1
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
返回:成功为指向结果的指针,出错为NULL

这两个函数对于IPv4和IPv6都适用。p代表表达式(presentation)和数值(numeric)。第一个函数尝试转化有strptr指针所指的字符串,通过addptr指针存放二进制结果,成功返回1。假设对指定的family而言输入的不是有效的表达格式,那么返回0

inet_ntop进行相反的操作。假设len的值太小。不足以存放表达式结果,则返回一个空指针,并置error为ENOSPC

socket和connect函数

#include <sys/socket.h>
int socket(int family, int type, int protocol);
返回:成功返回非负描写叙述符,出错返回-1

socket函数指定期望的通信协议类型(比方使用IPv4的TCP、使用IPv6的UDP、Unix域字节流协议)和套接字字类型(字节流、数据报或原始套接字)

----socket函数的family常值------------

family            说明    

AF_INET       IPv4协议    

AF_INET6     IPv4协议 

AF_LOCAL   Unix协议域 

AF_ROUTE   路由套接字

AF_KEY         秘钥套接字

----------------------------------------------------

----socket函数的type常值----------------

SOCK_STREAM          字节流套接字

SOCK_DGRAM           数据报套接字

SOCK_SEQPACKET 有序分组套接字

SOCK_RAW                原始套接字

----------------------------------------------------

----socket函数的protocal常值----------

IPPROTO_CP       TCP传输协议

IPPROTO_UDP    UDP传输协议

IPPROTO_SCTP  SCTP传输协议

----------------------------------------------------

#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);
返回:成功为0。出错-1

TCP客户用connect函数来建立一个与TCPserver连接,sockfd是由socket函数返回的套接字描写叙述符,第二个、第三个參数各自是指向一个套接字地址结构的指针和该结构的大小,套接字结构必须含有server的IP地址和port号。假设connect失败后,就必须close当前的套接字描写叙述符并又一次调用socket。

bind和listen函数

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
返回:成功为0,出错-1

bind函数把一个本地协议地址赋予一个套接字。它仅仅是把一个协议地址赋予一个套接字,至于协议地址的含义则取决于协议本身。第二个參数指向协议地址结构的指针。第三个參数是协议地址的长度,对于TCP,调用bind函数能够指定一个port号,或指定一个IP地址,或两者都指定,也能够两者都不指定。

#include <sys/socket.h>
int listen(int sockfd, int backlog);
返回:成功返回0,出错-1

socket创建一个套接字时,它被如果为一个主动套接字,也就是说,它是一个将调用connect发起连接的一个客户套接字。listen函数把一个未连接的套接字转换为一个被动套接字,指示内核应接受指向该套接字的连接请求,调用listen函数将导致套接字从CLOSEE状态转换到LISTEN状态。第二个參数规定了内核应为对应套接字排队的最大连接个数。

(1)、未完毕连接队列:每个这种SYN分节相应当中一项:已由某个客户发出并到达server,而server正在等待完毕相应的TCP三路握手过程。这些套接字处于SYN_RCVD状态。

(2)、已完毕连接队列:每一个完毕TCP三路握手过程的客户相应当中一项,这些套接字处于ESTABLISHED状态。

accept函数

#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
返回:成功返回已连接描写叙述符(非负)。出错-1

假设accept成功,那么其返回值是由内核自己主动生成的一个全新套接字,代表与返回客户的TCP连接,函数的第一个參数为监听套接字。返回值为已连接套接字

server、client程序流程图

serverclient简单交互程序见:http://blog.csdn.net/u012796139/article/details/44984879

TCP状态转换图

recv和send函数

TCP流数据读写

#include <sys/socket.h>
ssize recv(int sockfd, void *buff, size_t nbytes, int flags);
ssize send(int sockfd, void *buff, size_t nbytes, int flags);
返回:成功为读入或写入的字节数,出错为-1

MSG_OOB    对于send。表明将要发送带外数据,TCP连接上仅仅有一个字节能够作为带外数据发送。对于recv,本标志表明即将要读入的是带外数据而不是普通数据。

MSG_PEEK  该标志适用于recv和recvfrom,它同意我们查看已可读取的数据,并且在系统不在recv和recvfrom返回丢弃其这些数据

注意的是,flags參数仅仅对send和recv的当前调用有效。当然也能够通过setsockopt系统调用永久性地修 改socket的某些属性

recvfrom和sendto函数

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);
ssize_t recvto(int sockfd, void *buf, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen);
返回:成功为读或写的字节数,失败为-1

前3个參数sockfd、buf、nbytes等同于read和write函数的3个參数:描写叙述符、指向读入或写出缓冲区的指针和读写字节数

recvmsg和sendmsg函数

#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
返回:成功则为读入或写出字节数,出错-1

msg參数是msghdr结构体类型指针

struct msghdr
{
void *msg_name; //socket地址
socklen_t msg_namelen; //socket地址长度
struct iovec *msg_iov; //分散的内存块
int iovlen; //分散内存块数量
void *msg_control; //指向辅助数据的起始地址
socklen_t msg_controllen; //辅助数据大小
int msg_flags; //复制函数中的flags參数,并在调用过程中更新
};
struct iovec
{
void *iov_base; //内存起始地址
size_t iov_len; //这块内存长度
}

iovec结构体封装了一块内存的起始地址和长度,msg_iovlen指定了这种iovec结构体有多少个,对于recvmsg而言,数据将被读取并放在msg_iovlen块分离的内存中。这些内存的位置和长度则由msg_iov指向的数组指定,这成为分散读(scatter read)。对于sendmsg而言,msg_iovlen块分散内存中的数据将被一块发送,这成为集中写(gather write)

msg_control和msg_controllen用于辅助数据的发送。

msg_flags成员无需设定,它会复制recvmsg/sendmsg的flags參数的内容以影响数据读写过程。recvmsg还会在调用结束前,将某些更新后的标志设置到msg_flags中。recvmsg/sendmsg的flags參数以及返回值的含义均与send/recv的flags參数返回值同样。

getsockname和getpeername函数

#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, &addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, &addrlen);
返回:成功为0。 出错为-1

getsockname获取sockfd相应的本端socket地址,并将其存储于address參数指定的内存地址,该socket长度存储于addrlen指向的变量中。getpeername获取远端的socket地址。

getsockope和setsockopt函数

#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t optlen);
返回:成功为0,出错-1

sockfd指向一个打开的套接字描写叙述符,level(级别)指定系统中解释选项的代码或为通用套接字代码,或为某个特定于协议的代码(比如IPv4、IPv6、TCP或SCTP)。

optval是一个指向某个变量(*optval)的指针,setsockopt从*optval的大小有最后一个參数指定。它对于setsockopt是一个值參数,对于getsockopt是一个值-结果參数。

注意:套接字选项粗分为两大类型:一是启用或禁止某个特性的二元选项(成为标志选项),二是取得并返回我们能够设置或检查的特定值的选项(称为值选项)。标有 “标志”的列指出一个选项是否是标志选项,当给这些标志选项调用getsockopt函数时。*optval是一个整数。*optval中返回的为0表示对应选项被禁止。不为0表示对应选项被启动。类似的,setsockopt须要一个不为0的*optval来启动选项。一个为0的*optval来禁止选项。

假设标志中没有”.”,那么对应选项用于在用户进程和系统之间传递所指定的数据类型的值。

SO_RCVBUF和SO_SNDBUF套接字选项

每一个套接字都有一个发送缓冲区和一个接收缓冲区,接收缓冲区被TCP、UDP和SCTP用来保存收到的数据,直到由应用进程来读取。对于TCP来说,套接字接收缓冲区中可用的空间限制大小了TCP通告窗体的大小。

TCP套接字缓冲区不可能溢出,由于不同意对端发出超过该窗体大小的数据,本端TCP将丢弃他们。对于UDP是没有流量控制的:较快的发送端能够非常easy地淹没较慢得接收端,导致接收端的UDP丢弃数据。其实较快的发送端甚至能够淹没本机的网络接口,导致数据报被本机丢弃。

当设置TCP套接字接收缓冲区的大小时。函数调用的顺序非常重要,由于TCP窗体规模选项是在建立连接时用SYN分节与对端交换得到的。对于client,这意味着SO_RCVBUF选项必须在调用connect之前设置;对于server,这意味着该选项必须在调用listen之前对套接字进行设置。对已连接的套接字设置该选项对可能存在的窗体规模选项没有不论什么影响,由于accept直到TCP三次握手完毕才会创建并返回已连接套接字。这就是必须给监听套接字进行该选项设置的原因,套接字缓冲区大小是由新创建的已连接套接字从监听套接字继承来的。

gethostbyname函数

#include <netdb.h>
struct hostent *gethostbyname(const char *hostname);
返回:成功为非空指针,出错为NULL并设置h_errno

函数返回的非空指针结构例如以下的hostent结构

struct hostent
{
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length; /* length of address: 4 */
char **h_addr_list;
}

依照DNS的说法。gethostbyname运行的是A记录的查询(DNS的资源记录有A、AAAA、PTR、MX、CNAME等),它仅仅能返回IPv4地址,注意,该函数返回的是struct hostent *结构

gethostbyaddr函数

#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int fanily);
返回:成功为非空指针,出错为NULL并置h_errno

addr參数事实上并非char *结构,而是一个指向存放IPv4地址的in_addr结构的指针,len參数是这个结构的大小,对于IPv4,family參数为AF_INET

getservbyname和getservbyport函数

#include <netdb.h>
struct servent *getservbyneme(const char *servname, const char *protoname);
struct servent *getservbyport(int port, const char *protoname);
返回:成功为非空指针,出错为NULL

函数返回的非空指针指向例如以下结构:

struct servent
{
char *s_name;
char *s_aliases; /* alias list */
int s_port;
char *s_proto;
}

从名字到端口号的映射关系一般保存在一个文件里(一般是/etc/services)

       getservbyname的參数servname必须指定。假设同一时候指定了protoname(为非空指针),那么指定的服务必须和协议匹配。假设protoname未指定,而servname指向服务支持多个协议,那么返回那个port号取决于实现。通常没有关系,由于多个协议同样的服务一般有同样的TCP和UDPport号,但这点并没有保证

getservbyport的port參数必须是网络序

使用实例:

struct servent *pserv;

pserv = getservbyname(“ftp”, “tcp”);

pserv = getservbyport(htons(80), “tcp”);

參考:

1、《UNIX网络编程》第4章 第11章

2、《Linux高性能server编程》第5章 Linux网络编程基础API

3、server、client简单交互程序 http://blog.csdn.net/u012796139/article/details/44984879

网络编程API-上 (基本API)的更多相关文章

  1. Windows Embedded Compact 7网络编程概述(上)

    如今,不论是嵌入式设备.PDA还是智能手机,网络都是必不可少的模块.网络使人们更方便地共享设备上的信息和资源.而且,利用智能手机浏览互联网,也逐渐成为生活中的常见手段.物联网所倡导的物物相联,也离不开 ...

  2. python网络编程-socket上传下载文件(包括md5验证,大数据发送,粘包处理)

    ftp server 1) 读取文件名 2)检查文件是否存在 3)打开文件 4)检查文件大小 5)发送文件大小给客户端 6)等客户端确认 7)开始边读边(md5计算)发数据 8)给客户端发md5 ft ...

  3. python网络编程--FTP上传文件示例

    1.基础版(供学习了解原理使用,low) server服务端 import socket import struct import json server = socket.socket() ip_p ...

  4. 服务器编程入门(4)Linux网络编程基础API

      问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字( ...

  5. Linux 高性能服务器编程——Linux网络编程基础API

    问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字(so ...

  6. UNIX网络编程——揭开网络编程常见API的面纱【下】

    Linux网络编程数据收发的API流程分析        只要把数据在协议栈中的流动线路和脉络弄清楚了,关于协议栈的实现部分,理解起来就轻松多了.在网络编程章节的数据接收过程中,我们主要介绍过read ...

  7. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  8. JAVA的网络编程

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  9. JAVA网络编程【转】出处不详

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  10. 【转】JAVA之网络编程

    转自:火之光 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者 ...

随机推荐

  1. ACM比赛(第二次A)

    ime Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description There is ...

  2. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  3. 黑龙江省第七届大学生程序设计竞赛-Mysterious Organization

    描述 GFW had intercepted billions of illegal links successfully. It has much more effect. Today, GFW i ...

  4. hdu 4614 Vases and Flowers (二分 线段树)

    题目大意:爱丽丝有N个花瓶,每个花瓶最多放一朵花.然后又如下两个操作. 1:A B    从第A个花瓶开始,往后依次插B朵花,直到不能插为止.如果一朵花都不能插入就输出“can.....”,否则输出第 ...

  5. Android使用学习之画图(Canvas,Paint)与手势感应及其应用(乒乓球小游戏)

    作为一个没有学习Android的菜鸟,近期一直在工作之外努力地学习的Android的使用. 这周看了下Android的画图.主要是Canvas,Paint等,感觉须要实践下.下午正好有空,就想整一个乒 ...

  6. Ubuntu14.04更新源

    Ubuntu14.04更新源 http://jingyan.baidu.com/article/7f41ecec1b7a2e593d095ce6.html Ubuntu源 http://wiki.ub ...

  7. Windows Services的1053错误的解决办法之一:修改注册表允许的响应时间

    Error: 'The service did not respond in a timely fashion' (ServicesPipeTimeout) when attempting when ...

  8. iOS &quot;The sandbox is not in sync with the Podfile.lock&quot;解决方式

    更新Cocoapod之后出现故障: diff: /../Podfile.lock: No such file or directory diff: Manifest.lock: No such fil ...

  9. 在SharePoint 2013 中使用文档库Scheduling (计划公布功能)

    本文讲述在SharePoint2013 中使用文档库Scheduling (计划公布功能)的步骤和注意的事项. 文档库Scheduling (计划公布功能) 用于设定当文档通过审批后特定的时间区间内才 ...

  10. Maven项目红色叹号+JavaWeb: 报错信息The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java B

    昨天写的关于解决JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the ...