Linux/UNIX套接字连接
套接字连接
套接字是一种通信机子。凭借这样的机制。客户/server系统的开发工作既能够在本地单机上进行。也能够夸网络进行。
套接字的创建和使用与管道是有差别的。由于套接字明白地将客户和server区分开来。
套接字连接:
首先,server应用程序用系统调用socket来创建一个套接字,它是系统分配给该server进程的类似文件描写叙述符的资源,它不能与其它进程共享。
接下来。server进程会给套接字起个名字。本地套接字的名字是Linux文件系统中的文件名称,对于网络套接字它的名字是与客户连接的特定网络有关的服务标识符。这个标识符同意Linux将进入的针对特定port号的连接转到正确的server进程。
我们用bind来给套接字命名。然后server进程就開始等待客户连接到这个命名的套接字。
系统调用listen的作用是。创建一个队列并将其用于存放来自客户的进入连接。server通过系统调用accept来接受客户的连接。
server调用accept时。它会创建一个与原有的命名套接字不同的新套接字。这个套接字仅仅用于与这个特定的客户进行通信,而命名套接字则被保留下来继续处理来自客户的连接。
基于套接字系统的client更简单。
客户首先调用socket创建一个未命名套接字,然后将server的命名套接字作为一个地址来调用connect与server建立连接。
套接字属性
套接字的特性由三个属性确定:域、类型和协议。套接字还用地址作为它的名字。地址的格式随域的不同而不同。每一个协议又能够使用一个或多个地址来定义格式。
套接字的域
域指定套接字通信中使用的网络介质。
最常见的套接字域是AF_INET,它指的是互联网络。其底层协议——网际协议仅仅有一个地址族。它使用一种特定的方式来指定网络中的计算机,即人们常说的IP地址。
server计算机上可能同一时候有多个服务正在执行。
客户能够通过IPport来指定一台联网机器上的某个特定服务。在系统内部,port通过分配一个唯一16位的整数来标识,在系统外部,则须要通过IP地址和port号的组合来确定。
套接字作为通信的终点。必须在開始通信之前绑定一个port。
套接字域还能够是AF_UNIX,即使一台还未联网的计算机上的套接字也能够使用这个域。这个域的底层协议就是文件输入/输出,而他的地址就是绝对路径的文件名称。
我们的服务器套接字的地址是server_socket。
套接字类型
一个套接字域可能有多种不同的通信方式,而每种通信方式又有不同的特性。
AF_UNIX域的套接字没有这种问题。由于他们提供一个可靠的双向通信路径。
因特网协议提供两种不同的服务:流和数据报
流套接字:
流套接字提供一个有序、可靠、双向字节流的连接。因此,发送的数据能够确保不会丢失、复制或乱序到达,而且在这一过程中发生的错误也不会显示出来。流套接字由类型SOCK_STREAM指定,他们是在AF_INET域中通过TCP/IP连接实现。
他们也是AF_UNIX域中最常见的套接字类型。
数据报套接字
由类型SOCK_DGRAM指定的数据报套接字不建立和维持一个连接。它对能够发送的数据报的长度有限制。
数据报作为一个单独的网络消息被传输,可能会丢失、复制或乱序到达。
数据报套接字是在AF_INET域中通过UDP/IP连接实现的,它提供的是一种无须的不可靠服务。但从紫云的角度来看,它们的开销比較小,由于不须要维持网络连接。
并且由于无需花费时间来建立。所以他们的速度也非常快。UDP代表的是数据报协议。
套接字协议
仅仅要底层的传输机制同意不止一个协议来提供要求的套接字类型。就能够为套接字选择一个特定的协议。
创建套接字
socket系统调用创建一个套接字并返回一个描写叙述符。该描写叙述符能够用来訪问该套接字。
#include<sys/types.h>
#include<sys/socket.h>
int socket(intdomain, int type, int protocol);
创建的套接字是一条通信线路的一个端点。
domain參数指定协议族,type參数指定这个套接字的通信类型。protocol參数指定使用的协议。
最常见的套接字是AF_UNIX和AF_INET。
前者用于实现UNIX文件系统的本地套戒指。后者用于网络套接字。
type取值包含SOCK_STREAM和SOCK_DGRAM。
通信所用的协议一般有套接字类型和套接字域决定,通常不须要进行选择。将protocol參数设置为0表示使用默认协议。
socket系统调用返回一个描写叙述符。
套接字地址
每一个套接字域都有其自己的格式。
对于AF_UNIX域套接字来说。它的地址由结构sockaddr_un来描写叙述,该结果定义在头文件sys/un.h中。
structsockrrd_un{
sa_family_t sun_family;
char sun_path[];
};
此处sun_family指定地址类型。sun_path为文件名称来指定套接字地址。
在AF_INET域中,套接字地址由结构socketaddr_in来指定,该结构定义在文件netinet/in.h中,至少包括下面几个成员:
structsocket_in{
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
};
IP地址结构in_addr定义为
struct in_addr{
unigned long int s_addr;
};
IP地址中的四个字节组成一个32位的值,一个AF_INET套接字由它的域、IP地址和port号来全然确定。
命名套接字
要想让通过socket调用创建的套接字能够被其它进程使用,server就必须给该套接字命名。这样,AF_UNIX套接字就会关联到一个文件系统的路径名。AF_INET套接字结汇关联到一个IPport。
#include<sys/types.h> /* See NOTES*/
#include <sys/socket.h>
int bind(intsockfd, const struct sockaddr *addr, socklen_t addrlen);
bind系统调用把參数addr中的地址分配给与文件描写叙述符socket关联的未命名套接字。地址结构的长度由參数address_len传递。
bind调用须要将一个特定的地址结构指针转化为指向通用地类型(struct sockaddr *)。
bind调用成功返回0,失败返回-1。
创建套接字队列
为了可以在套接字上接受进入的连接,server程序必须创建一个队列来保存未处理的请求。使用listen系统调用来实现这一工作。
#include<sys/types.h> /* See NOTES*/
#include <sys/socket.h>
int listen(int sockfd, int backlog);
在套接字队列中,等待处理的进入连接的个数不能超过backlog这个数字。再往后的连接将被拒绝。
接受连接
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr*addr, socklen_t *addrlen);
一旦server程序创建并命名了套接字后,它就能够通过accept系统调用来等待客户建立对该套接字的连接。
accept系统调用仅仅有当客户试图连接到由sockfd參数指定的套接字上时才返回。
这里的客户指,在套接字队列中排在第一个的未处理连接。accept函数将创建一个新套接字来和该客户进行通信,而且返回新套接字的描写叙述符。
新套接字的类型和server监听套接字类型一样。
套接字必须事先由bind调用命名,而且有listen调用给他分配一个连接队列。
连接客户的地址将被放入address參数指向的sockaddr结构中。
參数address_len指定客户结构的长度。假设客户地址的长度超过这个值,它将被截段。所以在调用accept之前,address_len必须被设置为预期的地址长度。
当这个调用返回时,address_len将被设置为连接客户地址结构的实际长度。
假设套接字队列中没有未处理的联结,accept将被堵塞直到有客户建立连接为止。能够通过对套接字文件描写叙述符设置O_NOBLOCK标志来改变这一行为,使用函数fcntl。
请求连接
客户通过一个在未命名套接字和server监听套接字之间建立连接的方法来连接到server。
#include <sys/types.h>
#include <sys/socket.h>
int connect(intsockfd, const struct sockaddr *addr, socklen_t addrlen);
參数sockfd指定的套接字将连接到參数addr指定的server套接字,addr指向的结构的长度由參数addrlen指定。
关闭套接字
能够通过close函数来终止server和客户上套接字的连接。
主机字节序和网络字节序
为了使不同计算机能够通过网络传输的多字节整数的值达成一致,须要一个网络字节序。
客户和server必须在传输之前,将它们的内部整数表示方式转换为网络字节序。
能够通过下面函数完毕这一工作。
#include<arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_thtons(uint16_t hostshort);
uint32_tntohl(uint32_t netlong);
uint16_tntohs(uint16_t netshort);
htonl表示”host tonetwork ,long”。
网络信息
通过调用gethostent,能够找到给定计算机主机信息
#include<netdb.h>
Struct hostent *gethostent (void);
Void sethostent (int stayopen);
Void endhostent (void);
Struct hostent{
Char *h_name;
Char **h_aliases;
Inth_addrtype;
Inth_length;
Char **h_addr_list;};
从接口获得网络名字和网络号:
#include<netdb.h.
Struct netent * getnetbyaddr (uint32_t net,int type);
Struct netent * getnetbyname (const char *name);
Struct netent * getnetent (void);
Void setnetent (int stayopen);
Void endnetent (void);
Struct netent{
Char *n_name;
Char **n_aliases;
Intn_addrtype;
Uint32_t n_net;};
将协议名字和协议号採用下面函数映射
#include <netdb.h>
Struct protoent * getprotobyname (const char* name);
Struct protoent * getprotobynumber (intproto);
Struct protoent * getprotoent (void);
Void setprotoent (int stayopen);
Void endprotoent (void)。
Struct protoent{
Char *p_name;
Char **p_aliases;
Intp_proto;};
从一个服务名映射到一个port号,服务名
#include<netdb.h>
Struct servent * getservbyname (const char *name, const char * proto);
Struct servent * getservbyport (int port,const char * proto);
Struct servent * getservent( (void);
Void setervent (int stayopen);
Void endservent (void);
Struct servent{
Char *s_name;
Char **s_aliases;
Ints_port;
Char *s_proto;};
从一个主机名字和服务名字映射到一个地址
#include <sys/socket.h>
#include <netdb.h>
Int getaddrinfo (const char * restrict host,const char * restrict service, const struct addrinfo * restrict hint, structaddrinfo ** restrict res);
Void freeaddrinfo (struct addrinfo * ai);
Struct addrinfo{
Intai_flags;
intai_family;
Intai_socktype;
Intai_protocol;
Socklen_t ai_addrlen;
Structsockaddr * ai_addr;
Char *ai_canonname;
Structaddrinfo * ai_next;};
gai_strerror将返回的错误码转换成错误消息
#include<netdb.h>
Const char * gai_strerror (int error);
将地址转换成主机或者服务名
#include<sys/socket.h>
#include <netdb.h>
Int getnameinfo (const struct sockaddr *restrict addr, socklen_t alen, char * restrict host,socklen_t hostlen, char *restrict service, socklen_t servlen, unsigned int flags);
传输数据
发送数据:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr,socklen_t addrlen);
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
size_t msg_controllen; /* ancillary databuffer len */
int msg_flags; /*flags on received message */
};
接收数据:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr,socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
套接字选项
#include<sys/types.h> /* See NOTES*/
#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,
const void *optval,socklen_t optlen);
能够用以上函数来设定和获取套接字选项。
Linux/UNIX套接字连接的更多相关文章
- fsockopen — 打开一个网络连接或者一个Unix套接字连接
fsockopen (PHP 4, PHP 5, PHP 7) 说明 resource fsockopen ( string $hostname [, int $port = -1 [, int &a ...
- Linux:【解决】无法连接 MKS:套接字连接尝试次数太多正在放弃
[解决]无法连接 MKS:套接字连接尝试次数太多正在放弃 操作: 我的电脑 -> 右键 -> 管理 -> 服务和应用程序 -> 服务: 开启下面的服务: 服务启动成功后,重 ...
- 关于linux 原始套接字编程
关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...
- 解决VMware虚拟机报错“无法连接MKS:套接字连接尝试次数太多,正在放弃”
1.错误描述 在VMware中打开虚拟机时报错: "无法连接MKS:套接字连接尝试次数太多,正在放弃" 物理机操作系统: Windows 7 虚拟机操作系统: Kali Linux ...
- PHP Socket(套接字连接)扩展简介和使用方法
PHP socket扩展是基于流行的BSD sockets,实现了和socket通讯功能的底层接口,它可以和客户端一样当做一个socket服务器. 使用这些函数时请注意,虽然他们中有很多和C函数同名的 ...
- WCF 套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的
一个项目需要用到推送的功能,就是服务器主动推送数据给多台客户机.于是采用了WCF的双工通讯netTcpBinding 写好的项目,在本机测试都没有问题. 如果放在局域网内测试,问题出来了:先是安全性问 ...
- VMware Workstation “无法连接 MKS: 套接字连接尝试次数太多;正在放弃。” 解决方法【转】
今天和往常一样打开电脑,打开VMware Workstation,打开其中的一台虚拟机,以前都是这么打开没有问题,今天打开虚拟机突然提示“无法连接 MKS: 套接字连接尝试次数太多:正在放弃.”. 经 ...
- 【转载】Linux下套接字学习
感觉这个系列还不错,学习一下. 先看的是第三篇: http://blog.csdn.net/gatieme/article/details/46334337 < Linux下套接字详解(三)-- ...
- [转]如何借助 TLS/SSL 确保套接字连接的安全(使用 C#/VB/C++ 和 XAML 的 Windows 应用商店应用)
本文转自:http://msdn.microsoft.com/zh-cn/library/windows/apps/jj150597.aspx 本主题将展示在使用 StreamSocket 功能时,如 ...
随机推荐
- cxf WebService整理 (基于注解)
http://blog.csdn.net/zjw10wei321/article/details/39889823
- DbProviderFactories.GetFactory Oracle.ManagedDataAccess.Client
因为最近项目,要使用微软的EF框架不安装Oracle客户端的情况下,访问Oracle数据库.调用如下代码的时候会报错. System.Data.Common.DbProviderFactories.G ...
- maven在mac上的入门使用
首先博主也是在入门学习,在学习maven时遇到了不少问题.查资料时发现网上maven的使用大多是win的,所以我打算写点maven在mac入门使用的笔记,希望可以帮助到跟我一样有困难的你们. 1.ht ...
- 【USACO 3.3.2】商品购物
[描述] 在商店中,每一种商品都有一个价格(用整数表示).例如,一朵花的价格是 2 zorkmids (z),而一个花瓶的价格是 5z .为了吸引更多的顾客,商店举行了促销活动. 促销活动把一个或多个 ...
- 【COGS495】窗口
[问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表: Window position Min value Max val ...
- HDU 4632 CF 245H 区间DP(回文)
先说HDU 4632这道题,因为比较简单,题意就是给你一个字符串,然后给你一个区间,叫你输出区间内所有的回文子序列,注意是回文子序列,不是回文字串. 用dp[i][j]表示区间[i,j]内的回文子序列 ...
- 将与系统时间格式不同的字符串格式化为DATETIME类型
若系统时间格式为2012/03/05 08:12:12,那么若将("2012-03-05 08:12:12")格式化为时间变量时会报错,在转化之前先将系统时间格式改变再转换就不会报 ...
- html a标签
<a> 标签定义超链接,用于从一张页面链接到另一张页面. <a> 元素最重要的属性是 href 属性,它指示链接的目标. 在所有浏览器中,链接的默认外观是: 未被访问的链接带有 ...
- 解决SQL Server Management Studio Express不支持更新全文目录的方法
微软的说法:https://msdn.microsoft.com/zh-cn/library/ms365247.aspx 可以用命令创建: A.创建唯一索引.全文目录和全文索引 以下示例对 Adven ...
- exit() die return 的区别
rutrun 会返回一个值,或不返回值 只是当前函数内return后面的语句将不会执行,后面的其它语句继续执行exit()可以返回值,也可以不返回值直接终止程序 函数输出一条消息,并退出当前脚本. 会 ...