大家好,如果您还对服务器socket不太了解,没有关系,今天就由本站为大家分享服务器socket的知识,包括socket是什么呀的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!
一、socket是什么呀
套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议*数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。
可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。
套接字通常和同一个域中的套接字*数据(数据*也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Inter协议簇来进行通信。
Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。
通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket中,该 Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket中,使对方能够接收到这段信息。
Socket是由IP和端口结合的,提供向应用层进程传送数据包的机制。
类型
1、数据报套接字
无连接套接字,使用用户数据报协议(UDP)。在数据报套接字上发送或接收的每个数据包都单独寻址和路由。数据报套接字不能保证顺序和可靠*,因此从一台机器或进程发送到另一台机器或进程的多个数据包可能以任何顺序到达或可能根本不到达。在数据报套接字上发送广播可能需要特殊配置。
为了接收广播数据包,数据报套接字不应该绑定到特定,尽管在某些实现中,当数据报套接字绑定到特定时也可能接收广播数据包。
2、流套接字
面向连接的套接字,使用传输控制协议(TCP)、流控制传输协议(SCTP)或数据报拥塞控制协议(DCCP)。流套接字提供了无记录边界的有序且独特的无错误数据流,并具有用于创建和销毁连接以及报告错误的明确定义的机制。
流套接字以带外功能可靠地、有序地传输数据。在 Inter上,流套接字通常使用 TCP实现,以便应用程序可以使用 TCP/IP协议在任何网络上运行。
3、原始套接字
允许发送和接收 IP数据包,无需任何特定于协议的传输层格式。对于其他类型的套接字,根据选择的传输层协议(例如 TCP、UDP)自动封装有效载荷,并且套接字用户不知道与有效载荷一起广播的协议头的存在。从原始套接字读取时,通常包含标头。
从原始套接字传输数据包时,自动添加标头是可选的。
大多数套接字应用程序编程接口(API),例如基于Berkeley套接字的那些,支持原始套接字。Windows XP于 2001年发布,在Winsock接口中实现了原始套接字支持,但三年后,微软出于安全考虑限制了 Winsock的原始套接字支持。
原始套接字用于与安全相关的应用程序,如Nmap。原始套接字的一个用例是在用户空间中实现新的传输层协议。
原始套接字通常在网络设备中可用,用于路由协议,例如Inter组管理协议(IGMP)和开放最短路径优先(OSPF),以及用于Inter控制消息协议(ICMP)等事情,由ping实用程序。
以上内容参考百度百科-套接字
二、如何建立"socket"连接
一般socket有以下两种方式:长(常)和短。
长:当数据发送完成后socket不断开。一直保留到异常或者是程序退出为止,这种方式的好处是不用每次去发起连接断开,在速度上可以比短连接要快一些,但是相对来说对服务器的资源压力也要大些。长用的范围很广,比如游戏系统,qq等等,长(常)一般还需要定时向服务器ping数据,以保证socket畅通。当ping不通服务器时,需要重新开启。
短:当一次数据发送完毕后,主动断开,每次发送数据都要一次、断开操作,这种方式的好处是:对服务器的资源占用相对来说比较小,但是由于每次都要重新,速度开销上也比较大,这种方式对于那种不需要经常与服务器交互的情况下比较适用。
上面两种方法在用户量非常大的情况下都存在着很大的不足,因此,考虑可以用一种折衷的办法,那就是使用socket的连接池。
程序一开始初始化创建若干数量的长。给他们设置一个标识位,这个标识位表示该是否空闲的状态。当需要发送数据的时候,系统给它分配一个当前空闲的。同时,将得到的设置为“忙”,当数据发送完毕后,把标识位设置为“闲”,让系统可以分配给下个用户,这样使得两种方式的优点都充分的发挥出来了。用户数量足够多的时候,只需要动态增加池的数量即可。
下面我们用具体的程序来讲解下:
首先*一个socket类:
public class XieGouSocket
{
public Socket m_socket;//Socket对象
public bool m_isFree;//判断是否空闲
public int m_index;//在缓存池中的索引值
}
下面的函数是创建socket池,这里为了使代码更加清晰,特地把异常处理部分全部取掉了。
public XieGouSocket[] m_socket;//先定义个缓冲池
public void CreateSocketPool()
{
string ip=“127.0.0.1”;
string port= 2003;
IPAddress serverIp=IPAddress.Parse(ip);
int serverPort=Convert.ToInt32(port);
IPEndPoint iep=new IPEndPoint(serverIp,serverPort);
m_socket= new XieGouSocket[200];
for(int i=0; i< 200; i++)
{
m_socket[i]= new XieGouSocket();
m_socket[i].m_index= i;
m_socket[i].m_isFree= true;
m_socket[i].m_socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
m_socket[i].m_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout,1000);
m_socket[i].m_socket.Connect(iep);
}
}
下面的函数是获取当前空闲的socket:
因为是多线程,所以需要加一个原子操作,定义一个原子变量,以防止多个线程之间抢占资源问题的发生。
private static Mutex m_mutex=new Mutex();
public static XieGouSocket GetFreeConnection()
{
m_mutex.WaitOne();//先阻塞
for(int i=0; i< m_socket.Length; i++)
{
if(m_socket[i].m_isFree)//如果找到一个空闲的
{
m_socket[i].m_isFree= false;
m_mutex.ReleaseMutex();//释放资源
return m_socket[i];
}
}
//如果没有空闲的,要么等待,要么程序再动态创建一个。
m_mutex.ReleaseMutex();//释放资源
return null;
}
当数据发送完毕后,程序必须将m_isFree设置为 False。否则只使用不释放,程序很快就溢出了。
三、什么是Socket
什么是socket?
你经常听到人们谈论着“socket”,或许你还不知道它的确切含义。现在让我告诉你:它是使用标准Unix文件描述符(filedescriptor)和其它程序通讯的方式。什么?你也许听到一些Unix高手(hacker)这样说过:“呀,Unix中的一切就是文件!”那个家伙也许正在说到一个事实:Unix程序在执行任何形式的I/O的时候,程序是在读或者写一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数。但是(注意后面的话),这个文件可能是一个网络连接,FIFO,管道,终端,磁盘上的文件或者什么其它的东西。Unix中所有的东西就是文件!所以,你想和Inter上别的程序通讯的时候,你将要使用到文件描述符。你必须理解刚才的话。现在你脑海中或许冒出这样的念头:“那么我从哪里得到网络通讯的文件描述符呢?”,这个问题无论如何我都要回答:你利用系统调用socket(),它返回套接字描述符(socketdescriptor),然后你再通过它来进行send()和recv()调用。“但是...”,你可能有很大的疑惑,“如果它是个文件描述符,那么为什么不用一般调用read()和write()来进行套接字通讯?”简单的答案是:“你可以使用!”。详细的答案是:“你可以,但是使用send()和recv()让你更好的控制数据传输。”存在这样一个情况:在我们的世界上,有很多种套接字。有DARPAInter(Inter套接字),本地节点的路径名(Unix套接字),CCITTX.25(你可以将X.25套接字完全忽略)。