摘要:一般来说,服务器的套接字端口通常是某个知名端口,而客户端端口由内核自动分配。一个连接是由两端的套接字地址唯一确定的。
如果你点进了这个文章,我建议你直接访问 http://beej.us/guide/bgnet/ou... 学习socket编程,下面的资料是在读CSAPP时的一些总结,已经过时。
从programmer的角度,我们们可以把因特网看成一个世界范围内的主机集合,满足以下要求:
主机集合被映射为一组32位的ip地址
这组ip地址被映射为一组称为因特网域名的标识符
主机上的进程能够通过连接和其他主机上的进程通信
1.ip地址ip地址是一个32位无符号整数,网络程序将ip地址存储在如下结构中:
#includestruct in_addr{ unsigned int s_addr; // big endian }
注意,tcp/ip为任意整数数据定义了统一的网络字节顺序:大端字节顺序。并提供了以下方法来在网络和主机间进行字节顺序的转换:
#include/* 32位/16位主机转网络 */ unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); /* 32位/16位网络转主机 */ unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort);
ip地址还可以使用点分十进制表示法,所以系统提供了以下函数实现无符号整数和点分十进制表示方法的转换:
#include2.因特网域名/* 点分表示->整数 * 若成功返回1,出错返回0 */ int inet_aton(const char *cp,struct in_addr *inp); /* 整数->点分表示 * 返回指向点分十进制字符串的指针 */ char *inet_ntoa(struct in_addr in);
因特网定义了域名集合和ip地址集合之间的映射,这个映射是通过分布在世界范围内的数据库来维护的。从概念上讲,DNS数据库由上百万如下所示的主机条目结构组成,其中每条定义了一组域名和一组ip地址之间的映射。
#includestruct hostent{ char *h_name; //主机的官方域名 char **h_aliases; //别名的字符串数组 int addrtype; //地址类型,一般是AF_INET int h_length; //地址的字节长度 char **h_addr_list; //字符串数组 }
网络程序通过调用下面的函数,从DNS数据库检索主机条目(for myself csapp 622)
#include3.连接 & 套接字结构/* 通过域名检索 * 若失败,返回NULL,并设置h_errno */ struct hostent *gethostbyname(const char *name); /* 通过ip地址检索,第二个参数为地址的字节长度 * 若失败返回NULL,并设置h_errno */ struct hostent *gethostbyaddr(const char *addr,int len,0);
一个套接字是连接的一个端点,每个套接字都有相应的地址,是由一个因特网地址和一个16位的整数端口组成,一般用 “地址:端口”来表示。一般来说,服务器的套接字端口通常是某个知名端口,而客户端端口由内核自动分配。
一个连接是由两端的套接字地址唯一确定的。
套接字地址存放在如下所示的结构中:
#include4.socket 函数#include /* 这个结构是为了函数 connect、bind、accept而设计的 */ struct sockaddr{ unsigned short sa_family; //protocol family char sa_data[14]; //address data } /* 套接字地址结构 */ struct sockaddr_in{ unsigned short sin_family; //address family 一般为AF_INET unsigned short sin_port; //大端表示的接口 struct in_addr sin_addr; //大端表示的ip地址 unsigned char sin_zero[8]; //pad to sizeof(struct sockaddr) }
客户端使用函数的顺序是 socket->connect
服务端使用函数的顺序是 socket->bind->listen->accept
#include#include /* 创建套接字描述符,成功返回描述符,失败返回-1 * 一般总是这样使用:clientfd=socket(AF_INET,SOCK_STREAM,0); */ int socket(int domin,int type,int protocol);
socket返回的描述符还不能用于读写,在客户端和服务端要经过不同的处理,如前文的顺序所示。
#include/* 客户端使用该函数建立与服务器的连接 * 成功,返回0;失败,返回-1 */ int connect(int sockfd,struct sockaddr *serv_addr,int addrlen); /* 服务端使用该函数将服务器的地址和描述符连接起来 * addrlen是 sizeof(sockaddr_in) * 成功返回0,否则-1 */ int bind(int sockfd,struct sockaddr *my_addr,int addrlen); /* 服务端使用该函数将一个主动套接字改为监听套接字 * 成功返回0,失败-1 */ int listen(int sockfd,int backlog);
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/9567.html
摘要:一网络编程基础网络编程本身是一门很大的学问,涉及到的东西也很多,尤其是各种协议。套接字允许应用程序将插入网络中,并与网络中的其他应用程序进行通信。端口的存在,主要是为了确认消息一一对应性。 一、网络编程基础 网络编程本身是一门很大的学问,涉及到的东西也很多,尤其是各种协议。先看图: showImg(https://segmentfault.com/img/bVbvSnH?w=611&h...
摘要:对于连接,实际发起了三次握手,成功返回后连接就建立了。主进程负责新进的并创建子进程,子进程负责跟通信。由个函数协调完成,把整个过程分成了创建,配置,监控三步。监控参数说明实体标识指示发生的事情。如果有事件发生,通过事件链表的方式返回给。 在internet网络的世界里,socket可以说是最重要的任务间通讯的方式,尤其是当两个任务驻留在不同的机器上需要通过网络介质连接。今天系统复习一下...
摘要:对于连接,实际发起了三次握手,成功返回后连接就建立了。主进程负责新进的并创建子进程,子进程负责跟通信。由个函数协调完成,把整个过程分成了创建,配置,监控三步。监控参数说明实体标识指示发生的事情。如果有事件发生,通过事件链表的方式返回给。 在internet网络的世界里,socket可以说是最重要的任务间通讯的方式,尤其是当两个任务驻留在不同的机器上需要通过网络介质连接。今天系统复习一下...
摘要:选项前面讨论过连接的状态,并提到服务器程序可以通过设置选项来强制使用被处于状态的连接占用的地址。和选项和选项分别表示接收缓冲区和发送缓冲区的大小。此时选项不起作用,用默认行为关闭。 socket选项函数 功能:用来读取和设置socket文件描述符属性的方法 #include int getsockopt ( int sockfd, int level, int option_name...
摘要:文件描述符是一个整数索引值,是这个数组的下标。基于协议的基于的编程过程和有些不同。通过名字可以看出,这是在父进程的基础上完全拷贝一个子进程。因此父进程刚才因为创建的已连接也是一个文件描述符,同样也会被子进程获得。 系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP 是怎么来,又是怎么没的? 网络协议 3 - 从物理层到 MAC 层 网络协议 4 - 交换机与 VLAN:...
阅读 674·2021-11-24 09:39
阅读 3089·2021-10-27 14:20
阅读 2202·2019-08-30 14:08
阅读 3224·2019-08-29 16:34
阅读 2058·2019-08-26 12:14
阅读 1997·2019-08-26 11:54
阅读 2645·2019-08-26 11:44
阅读 2357·2019-08-26 11:38