socket的类型(socket包含哪些基本信息?)
socket的常用函数
函数原型:
int socket(int domain, int type, int protocol);
参数说明:
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(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
注意:1.type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。
2.WindowsSocket下protocol参数中不存在IPPROTO_STCP
返回值:
如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET(Linux下失败返回-1)。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。 函数原型:
int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
参数说明:
socket:是一个套接字描述符。
address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。
address_len:确定address缓冲区的长度。
返回值:
如果函数执行成功,返回值为0,否则为SOCKET_ERROR。 函数原型:
int recv(SOCKET socket, char FAR* buf, int len, int flags);
参数说明:
socket:一个标识已连接套接口的描述字。
buf:用于接收数据的缓冲区。
len:缓冲区长度。
flags:指定调用方式。取值:MSG_PEEK 查看当前数据,数据将被复制到缓冲区中,但并不从输入队列中删除;MSG_OOB 处理带外数据。
返回值:
若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。
函数原型:
ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);
参数说明:
sockfd:标识一个已连接套接口的描述字。
buf:接收数据缓冲区。
len:缓冲区长度。
flags:调用操作方式。是以下一个或者多个标志的组合体,可通过or操作连在一起:
(1)MSG_DONTWAIT:操作不会被阻塞;
(2)MSG_ERRQUEUE: 指示应该从套接字的错误队列上接收错误值,依据不同的协议,错误值以某种辅佐性消息的方式传递进来,使用者应该提供足够大的缓冲区。导致错误的原封包通过msg_iovec作为一般的数据来传递。导致错误的数据报原目标地址作为msg_name被提供。错误以sock_extended_err结构形态被使用。
(3)MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。
(4)MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长, 只对packet套接字有效。
(5)MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据。
(6)MSG_EOR:指示记录的结束,返回的数据完成一个记录。
(7)MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间。
/*(MSG_TRUNC使用错误,4才是MSG_TRUNC的正确解释)*/
(8)MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃。
(9)MSG_OOB:指示接收到out-of-band数据(即需要优先处理的数据)。
(10)MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据。
from:(可选)指针,指向装有源地址的缓冲区。
fromlen:(可选)指针,指向from缓冲区长度值。 函数原型:
int sendto( SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
参数说明:
s:套接字
buf:待发送数据的缓冲区
size:缓冲区长度
flags:调用方式标志位, 一般为0, 改变Flags,将会改变Sendto发送的形式
addr:(可选)指针,指向目的套接字的地址
tolen:addr所指地址的长度
返回值:
如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。 函数原型:
int accept( int fd, struct socketaddr* addr, socklen_t* len);
参数说明:
fd:套接字描述符。
addr:返回连接着的地址
len:接收返回地址的缓冲区长度
返回值:
成功返回客户端的文件描述符,失败返回-1。
SOCKET到底是什么类型
哈哈,我用自己的语言来说一下
打开英文词霸,发现socket的中文意思是插座的意思。
简言之socket就是:有插座,有插头,有电器(比如电灯)。
插座带电, 插头插入插座以后,就可以把电流通到电器里面去,这时候电灯就可以工作了。
引申一下呢:
插座:相当于服务端程序,他可以向客户(电器)提供资料,任何人只要满足一定条件就可以去服务端取资料(电流);
插头:就是socket,它是一种抽象的东西,也可以理解成一种规范,大家都承诺会尊守这一个规范,比如插头有三脚的,两脚的,四脚的,等等,大小也有规定。只要是插座能接受的就可以插入进去。
电流: 从服务器取下来的资料就可以认为是电流,可以供人参考查询等等。
电器: 我们的客户端程序就是电器,比如IE其实就是客户端程序,QQ也是。我们利用IE,给他指定一个网址,他就会利用HTTP协议去指定的服务器网站取下新闻等资讯给我们看。给我们看的过程需要程序进行分解,如播音乐、放动画等等;
socket的工作过程:
简述一下QQ聊天的工作原理。
假设腾讯公司建立了一个服务器,socketServer 并打开了 5555 这个端口
其实就是给了全中国的人一个插座,并且规定只接收规格是 5555的插头,大家都可以把插头插到腾讯公司的服务器上去取电流;
这时候玩家A 利用客户端 插上去了,于是他与服务器建立了通道。有电流的联系了,并且是双向的,他即可以向服务器取消息,又可以把消息发到服务器。
于是他向服务器发送了一条消息(电流)在消息中说明了想要说的话,并且指明要发给一个叫玩家B的人。
这时候服务器接收了这条消息,暂存。
过了一会儿,玩家B也插上去了插座,并向服务器发送了一条消息,说我上来了。
服务器检测到玩家B正好是之前玩家A要发送的对象,于是通过通道把消息发给了玩家B,这样玩家B就看到了玩家A说的话。
Connection :通道,连接,可以是Socket的。并且可以从中得到InputStream 和OutputStream;
OutputStream: 有了通道就可以以流的形式发送想要发送的东西,比方有了电线才可以把电流传到另一端,在网络中大家传送的都是字节流byte
inputStream: 有了通道就可以以流的形式接收想要收的东西。
现在可以通过OutputStream把想要说的话向服务器发送,通过Socket通道
也可以通过InputStream向服务器索要与自己相关的内容。
明白未?
SOCKET类型和CSOCKET有什么区别?
你这里说的SOCKET是一个变量类型,其实就是int类型。
而CSOCKET是一个类,已经包含了socket通信的一些对象和算法,这样定义一个对象之后,就可以直接调用这些算法,不用自己写了。
常用的socket有什么类型
关于AMD处理器的接口,目前主流的主要是Socket AM2/AM2+/AM3接口。其中,Socket AM2接口常见的是940pin,Socket AM2+常见的是940pin或939pin,Socket AM3常见的是938pin。其中,Socket AM2与AM2+接口基本是通用的,可以直接用,而要是不支持可以通过简单的升级,Socket AM2支持Socket AM2+。但是与Socket AM3接口就不同了。由于Socket AM2/AM2+接口的主板版本程序过老,再就是支持处理器的规格上的区别,要是想支持Socket AM3接口的处理器,一般需要升级主板BIOS。而目前主流的芯片组主板一般Socket AM2/AM2+/AM3接口都会兼容支持,而要是主板仅仅支持Socket AM3接口的话,是不能支持Socket AM2/AM2+处理器的,就算升级BIOS也没用。也就是说,只要主板BIOS支持,AM3接口的处理器是可以使用在AM2/AM2+的主板上的,但AM2/AM2+的CPU不能使用在AM3插槽的主板上。
同一端口,如何区分不同的socket
为了区分不同应用进程之间的网络通信和链接,主要有三个参数:通信的目的IP地址,使用的传输层协议(TCP / UDP)和使用的端口号。
Socket的愿意是插座,通过将这三个参数结合起来,与一个插座socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序或网络连接点额通信,实现数据传输的并发服务。
accept()产生的Socket端口号是多少?
要写网络程序就必须用Socket,这是程序员都知道的,而且在面试的时候,我们也会问对方会不会socket编程,很多人都会说Socket编程基本就是listen、accept、以及send 和write几个基本操作,是的就跟常见的文件操作一样,只要写过就一定知道。
对于网络编程我们言必称TCP,似乎其他的网络协议已经不存在了,对于TCP我们还知道UDP,前者可以保证数据的正确和可靠性,后者允许数据的丢失,最后我们还知道,在建立连接之前,必须知道对方的IP地址和端口号,除此,普通的程序员就不会知道的太多了,很多时候这些知识以及够用了,最多写服务程序的时候,会用多线程处理并发访问。
我们还知道以下几个事实
1.一个指定的端口号不能被多个应用程序公用,比如IIS占用了80端口,那么APACHE就不能用这个端口了。
2.很多防火墙只允许特定目标端口的数据包通过。
3.服务程序在listen某个端口并accept某个连接请求之后,会生成一个新的socket来对请求进行处理,
于是一个困惑我很久的问题产生了,如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?
如果是这样的,那么当其accept一个请求之后,生成的新的socket到底使用的是什么端口呢?(我一直以为系统会默认给其分配一个空闲的端口号)
如果是一个空闲的端口号,那么一定不是80端口了,于是以后的TCP数据包端口肯定就不是80 了--防火墙会阻止他通过的。
实际上我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接 请求和处理方式,我不理解的就是为什么防火墙没有阻止这样的连接,他是如何判断那条连接是因为connect80端口生成的?是不是TCP数据包里面有什么特别的标志,或者防火墙已经记住了什么东西?
后来我又仔细读了TCP/IP协议栈原理,对很多概念有了更深刻的认识,比如TCP和UDP同属于传输层,共同假设在IP层之上,而IP层主要负责在节点之间的数据包传输,这里的节点是一台网络设备,比如计算机,因为IP曾只负责把数据送到节点之上,而不能区分上面的不同应用,所以TCP、UDP在协议的基础上加入了端口的信息,端口是标识的是一个节点上的应用,处理增加端口信息,UDP协议基本就没有对IP层的数据进行任何处理了,而TCP协议还加入了更复杂的传输控制,比如滑动的数据发送窗口,以及接受确认和重发机制,以达到数据的可靠传输,不管应用层看到的是怎么样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。
所以我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号,而且我们也看到,所谓的端口是为了区分不同的应用的,以在不同的IP包来到的时候能够正确的转发。
TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口,就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP、IP也必须对外提供编程接口,这就是Socket编程接口--原来就是这么回事
在Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很相似,实际上,在BSD系统里就是跟文件句柄一样存放在一样的 进程句柄 里。 这个 socket其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等。 这些句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定对象进行操作 ——这其实是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。
现在我们知道,socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create, listen, accept, connect, read和write等。
明白socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系,这很重要!
昨天和朋友聊了下网络编程,关于Socket,这里写一下我个人的一些理解:)
程序里可以创建Socket,分为普通Socket和原始Socket两种类型。
一:普通Socket是对TCP/IP协议栈中传输层的操作的编程接口(一种API)。
有面向连接的流式套接字(SOCK_STREAM),属于针对TCP方式的应用;
有无连接数据包式套接字(SOCK_DGRAM),属于针对UDP方式的应用。
对于普通Socket,我曾经有个模糊的问题,在 多线程情况 下,服务器端监听(listen)某个端口(假设8080)后,每accept一个客户端的连接就会产生一个新的Socket。那么这些新产生的Socket的端口是什么?程序里肯定没有指定,那就应该有两种可能,1:产生随机端口。2:还是8080端口。第一种假设想了就觉得不可能,防火墙非常有可能会阻止这些随机端口的包。那么就是第二种假设了,服务端端口还是8080。但这推翻了我原有的认识,就是“一个端口被程序占有,其他程序就不能用该端口了”。我觉得其实最有可能的是范围不同:就是在程序与程序间不能用同一端口,但是在程序内部不同的Socket还是可以用同一端口的。所以,为了能够使“客户端发给服务端的同一端口(8080)不同线程(即不同的Socket连接)的包能够被区分开并进行组合”,必须得有一个区分包是来自不同连接的显著特征,那就是传输层包头里的源端口了,即一个Socket连接里客户端那方的端口。总结一下,对于这种情况,就是传输层包头里源端口(客户端)会随着产生的Socket不同,而宿端口相同(服务器端)。
很多疑问都在文章里里找到了答案,特别是“端口是用来区分不同应用程序的”,之前也困惑多线程下,每个线程建立连接的端口是否可以相同。 另外文中说每accept一个连接会得到一个新的socket,这个表述不是很完美,其实不是一个新的socket而是得到了客户端的socket,这个socket里的ip和端口当然是客户端的ip和端口了。表达accept客户端之后,服务端用的是哪个端口。
单个进程监听多个端口
单个进程创建多个 socket 绑定不同的端口,TCP, UDP 都行
多个进程监听同一个端口(multiple processes listen on same port)
通过 fork 创建子进程的方式可以实现,其他情况下不行。
多线程情况下,服务器端监听(listen)某个端口后,每accept一个客户端的连接就会产生一个新的Socket
新产生的Socket的端口是多少?
答案是服务器端口还是Listen端口。
进程间不能用同一端口,但是进程内部不同Socket可以用同一个端口。
Client端发送给Server同一端口的不同Socket怎么区分。
用Client端Socket端口区分!
Socket是TCP/IP协议的网络接口 socket是对TCP/IP协议操作的抽象
客户端connect函数是开始调用到函数返回正好是三次握手的过程,第三次握手成功则返回
server端三次握手之后内核调用accept函数,accept函数执行后会产生一个新的socket与client端进行连接。
Q:编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?
A:这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,
而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止
后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何
非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
端口复用最常用的用途应该是防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中——那只好等等再重试了,麻烦!
那如何让sockfd_one, sockfd_two两个套接字都能成功绑定8000端口呢?这时候就需要要到端口复用了。端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。
设置socket的SO_REUSEADDR选项,即可实现端口复用:
SO_REUSEADDR可以用在以下四种情况下。 (摘自《Unix网络编程》卷一,即UNPv1)
1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。
需要注意的是,设置端口复用函数要在绑定之前调用,而且只要绑定到同一个端口的所有套接字都得设置复用:
端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。同时,这 n 个套接字发送信息都正常,没有问题。但是,这些套接字并不是所有都能读取信息,只有最后一个套接字会正常接收数据。
接着,通过网络调试助手给这个服务器发送数据,结果显示,只有最后一个套接字sockfd_two会正常接收数据。
一个连接的唯一标识是[server ip, server port, client ip, client port]也就是说。操作系统,接收到一个端口发来的数据时,会在该端口,产生的连接中,查找到符合这个唯一标识的并传递信息到对应缓冲区。
所以说一个socket可以对应多个tcp连接。
socket是什么呀
套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。
可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。
套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Internet协议簇来进行通信。
Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。
通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket中,该 Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket中,使对方能够接收到这段信息。
Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。
类型
1、数据报套接字
无连接套接字,使用用户数据报协议(UDP)。在数据报套接字上发送或接收的每个数据包都单独寻址和路由。数据报套接字不能保证顺序和可靠性,因此从一台机器或进程发送到另一台机器或进程的多个数据包可能以任何顺序到达或可能根本不到达。在数据报套接字上发送广播可能需要特殊配置。
为了接收广播数据包,数据报套接字不应该绑定到特定地址,尽管在某些实现中,当数据报套接字绑定到特定地址时也可能接收广播数据包。
2、流套接字
面向连接的套接字,使用传输控制协议(TCP)、流控制传输协议(SCTP) 或数据报拥塞控制协议(DCCP)。流套接字提供了无记录边界的有序且独特的无错误数据流,并具有用于创建和销毁连接以及报告错误的明确定义的机制。
流套接字以带外功能可靠地、有序地传输数据。在 Internet 上,流套接字通常使用 TCP 实现,以便应用程序可以使用 TCP/IP 协议在任何网络上运行。
3、原始套接字
允许直接发送和接收 IP 数据包,无需任何特定于协议的传输层格式。对于其他类型的套接字,根据选择的传输层协议(例如 TCP、UDP)自动封装有效载荷,并且套接字用户不知道与有效载荷一起广播的协议头的存在。从原始套接字读取时,通常包含标头。
从原始套接字传输数据包时,自动添加标头是可选的。
大多数套接字应用程序编程接口(API),例如基于Berkeley 套接字的那些,支持原始套接字。Windows XP于 2001 年发布,在Winsock接口中实现了原始套接字支持,但三年后,微软出于安全考虑限制了 Winsock 的原始套接字支持。
原始套接字用于与安全相关的应用程序,如Nmap。原始套接字的一个用例是在用户空间中实现新的传输层协议。
原始套接字通常在网络设备中可用,用于路由协议,例如Internet 组管理协议(IGMP) 和开放最短路径优先(OSPF),以及用于Internet 控制消息协议(ICMP) 等事情,由ping 实用程序。
以上内容参考?百度百科-套接字