socket之创建、命名、监听、连接、关闭

创建socket

  UNIX/linux的一个哲学是:所有东西都是文件。socket就是可读、可写、可控制、可关闭的文件描述符。
  创建socket的API:
在这里插入图片描述
  domain:告诉系统使用哪个底层协议。例如对于TCP/IP协议族而言,为AF_INET或AF_INET6。
  type:指定服务类型。主要有SOCK_STREAM服务(流服务,对TCP/IP协议族而言表示传输层使用TCP协议)和SOCK_UGRAM(数据报,对TCP/IP协议族而言表示传输层使用UDP协议)服务。但自Linux内核2.6.17版本起,type参数可以接受服务类型与下面俩个重要的标志相与的值:SOCK_NONBLOCK和SOCK_CLOEXEC。分别表示将新创建的socket设为非阻塞的,以及用fork调用创建子进程时在子进程中关闭该socket。在此之前需要使用额外的系统调用。
  protocol:是在前两个参数构成的协议族集合下,再选一个具体的协议。不过通常前两个参数已经完全决定了所用的协议。所以,该值设置为0。表示使用默认协议。
  socket系统调用成功时返回一个socket文件描述符,失败返回-1并设置errno。

命名socket

  创建socket时,指定了地址族,但是并未指定使用该地址族中的那个具体socket地址。将一个socket与socket地址绑定称为给socket命名。在服务器程序中,我们通常要命名socket,因为只有命名后客户端才能知道该如何连接它。客户端通常不需要命名socket,而是采用匿名方式,即使用操作系统自动分配的socket地址。
  命名的socket的系统调用是bind,定义如下:
在这里插入图片描述
  bind将my_addr所指的socket地址分配给未命名的sockfd文件描述符,addrlen参数指定该socket地址的长度。
  bind成功时返回0,失败则返回-1并设置errno:(常见的两种errno)
在这里插入图片描述

监听socket

  socket被命名之后,还不能马上接收客户连接,我们需要使用如下系统调用来创建一个监听队列以存放待处理的客户连接:
在这里插入图片描述
  sockfd参数指定被监听的socket。backlog参数提示内核监听队列的最大长度。监听队列的长度如果超过backlog,服务器将不受理新的客户连接,客户端也将受到ECONNREFUSED错误信息。(在内核版本2.2之前的Linux中,backlog参数是指所有处于半连接状态和完全连接状态的socket的上限。在此之后,他只表示处于完全连接状态的socket上限,处于半连接状态的socket的上限则由/proc/sys/net/ipv4/tcp_max_syn_backlog内核参数定义。典型值为5)。
  listen成功时返回0,失败则返回-1,并设置errno。

接受socket连接

  下面的系统调用从listen监听队列中接受一个连接:
在这里插入图片描述
  sockfd参数是执行过listen系统调用的监听socket。addr参数用来获取被接受端socket地址,该socket地址的长度由addrlen参数指出。accept成功时返回一个新的连接socket,该socket唯一地标识了被接受的这个连接,服务器可通过读写该socket来与被接受连接对应的客户端通信。accept失败返回-1并设置errno。
  accetp只是从监听队列中取出连接,而不论连接处于何种状态,更不关心任何网络状况的变化。

socket连接和关闭

发起连接

  服务器通过listen调用来被动接受连接,客户端通过connect系统调用来主动连接服务器:
在这里插入图片描述
  sockfd参数由socket系统调用返回一个socket。serv_addr参数是服务器监听的socket地址,addrlen参数则指定这个地址的长度。
  connect调用成功返回0。一旦成功建立连接,sockfd就唯一地标识了这个连接,客户端就可以通过读写sockfd来与服务器通信。connect失败则返回-1并设置errno,常见的两种是ECONNREFUSED和ETIMEDOUT:
  ECONNREFUSED:目标端口不存在,连接被拒绝。
  ETIMEDOUT:连接超时。

关闭连接

  关闭连接实际就是关闭该连接对应的socket,可通过close系统调用来完成:
在这里插入图片描述
  fd参数是待关闭的socket。不过,close系统调用并非总是立即关闭一个连接,而是将fd的引用计数减一。只有当fd的引用计数为0时,才真正关闭连接。多进程程序中,一次fork系统调用默认将父进程中打开的socket的引用计数加一,因此,我们必须在父进程和子进程中都对该socket执行close调用才能将连接关闭。
  如果无论如何都要立即终止连接(而不是将socket的引用计数减一),可以使用如下的shutdown系统调用:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤来在服务器使用Socket创建服务器端,监听客户端的连接请求: 1. 引用命名空间:在代码中引用System.Net.Sockets命名空间,以便使用Socket类。 2. 创建Socket对象:使用Socket类的构造函数创建一个Socket对象。 ``` Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ``` AddressFamily.InterNetwork指定使用IPv4协议,SocketType.Stream指定使用流式套接字,ProtocolType.Tcp指定使用TCP协议。 3. 绑定IP地址和端口号:使用Bind方法将Socket对象绑定到指定的IP地址和端口号上。 ``` IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); listener.Bind(localEndPoint); ``` 这里使用了IP地址127.0.0.1和端口号8888。 4. 开始监听连接请求:使用Listen方法开始监听客户端的连接请求。 ``` listener.Listen(100); ``` 这里设置最大连接数为100,即同时最多允许100个客户端连接。 5. 接受连接请求:使用Accept方法接受客户端的连接请求,并返回一个新的Socket对象,用于与客户端进行通讯。 ``` Socket handler = listener.Accept(); ``` 这里使用了一个while循环,可以接受多个客户端的连接请求。 ``` while (true) { Socket handler = listener.Accept(); // 处理客户端请求 } ``` 注意:在处理完客户端请求后,需要关闭Socket对象。 可以根据业务需求,对接收到的客户端请求进行解析和处理。例如,可以使用StreamReader和StreamWriter类来读取和写入数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值