文章目录

  • 一、Socket网络编程
    • 1.Socket是什么?
    • 2.Socket本质
    • 3.Socket作用
    • 4.Socket的典型应用
  • 二、网络传输
    • (一)OSI网络七层模型
    • (二)网络模型
    • (三)IP地址和端口
      • 1.IP地址
      • 2.端口
    • (四)Socket/TCP五层网络模型
    • (五)TCP和UDP
      • 1.UDP:
      • 2.TCP:
  • 三、Socket/TCP
    • TCP报文
    • TCP三次握手
    • TCP四次挥手
  • 四、Socket编程
    • (一)Socket编程方式
    • (二)数据传输方式
      • 1. STREAM
      • 2.DGRAM
    • (三)服务器端编写步骤
    • (四)客户端编写步骤
    • (五)案例

一、Socket网络编程

1.Socket是什么?

在计算机通信领域,Socket被译为“套接字”。它是计算机之间进行通信的一种约定或一种方式。通过Socket这种约定可以接收到其他计算机的数据,也可以向其他计算机发送数据。

2.Socket本质

是编程接口(API),对于TCP/IP的封装,TCP/IP也提供了可供程序员做网络开发所用的接口

3.Socket作用

Socket的英文原意是“插座”,的意思,通常在计算机编程中称作套接字,可以用来实现不同虚拟机或不同计算机之间的通信

4.Socket的典型应用

(1)Socket的应用之一就是Web服务器和浏览器:浏览器获取用户输入的URL地址,向服务器发起请求,服务器分析接收到的URL请求,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,将文字、图片、视频等元素呈现给用户
(2)QQ或者微信或者默默等聊天社交工具等:本地的QQ或微信程序就是客户端,登录过程就是连接服务器的过程,聊天过程就是Socket的发送和接受信息过程

二、网络传输

(一)OSI网络七层模型

特点:

(1)人们可以很容易的讨论和学习协议的规范细节。
(2)层间的标准接口方便了工程模块化。
(3)创建了一个更好的互连环境。
(4)降低了复杂度,使程序更容易修改,产品开发的速度更快。
(5)每层利用紧邻的下层服务,更容易记住个层的功能。

(二)网络模型

网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算机。
现在的网络编程基本上都是基于请求/响应方式的,也就是一个设备发送请求数据给另外一个,然后接收另一个设备的反馈。
在网络编程中,发起连接程序,也就是发送第一次请求的程序,被称作客户端(Client),等待其他程序连接的程序被称作服务器(Server)。客户端程序可以在需要的时候启动,而服务器为了能够时刻相应连接,则需要一直启动。例如以打电话为例,首先拨号的人类似于客户端,接听电话的人必须保持电话畅通类似于服务器。

连接一旦建立以后,客户端和服务器端就可以进行数据传递了,而且两者的身份是等价的。

在一些程序中,程序既有客户端功能也有服务器端功能,最常见的软件就是BT、emule这类软件了。

(三)IP地址和端口

1.IP地址

IP地址是一个规定,现在使用的是IPv4,既由4个0-255之间的数字组成,在计算机内部存储时只需要4个字节即可。在计算机中,IP地址是分配给网卡的,每个网卡有一个唯一的IP地址,如果一个计算机有多个网卡,则该台计算机则拥有多个不同的IP地址,在同一个网络内部,IP地址不能相同。IP地址的概念类似于电话号码、身份证这样的概念。
由于IP地址不方便记忆,所以有专门创造了 域名(Domain Name) 的概念,其实就是给IP取一个字符的名字,例如163.com、sina.com等。IP和域名之间存在一定的对应关系。如果把IP地址类比成身份证号的话,那么域名就是你的姓名。
其实在网络中只能使用IP地址进行数据传输,所以在传输以前,需要把域名转换为IP,这个由称作DNS的服务器专门来完成。
所以在网络编程中,可以使用IP或域名来标识网络上的一台设备。

2.端口

可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算 机内部或交换机路由器内的端口,不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口,是可见端口,计算机背板的RJ45网口,交换机路由器集线器等RJ45端口。电话使用RJ11插口也属于物理端口的范畴。
规定一个设备有216个,也就是65536个端口,每个端口对应一个唯一的程序。每个网络程序,无论是客户端还是服务器端,都对应一个或多个特定的端口号。由于0-1024之间多被操作系统占用 ,所以实际编程时一般采用1024以后的端口号。

(四)Socket/TCP五层网络模型

(五)TCP和UDP

1.UDP:

(1) 面向无连接,将数据及源封装在数据包中,不需要建立连接
(2)每个数据报的大小限制在64K内
(3)因无连接,是不可靠协议
(4)不需要连接连接,速度快

2.TCP:

(1) 建立连接,形成传输数据的通道
(2)在连接中进行大数据量传输,以字节流的形式
(3)通过三次握手(四次挥手)完成连接,是可靠协议
(4)必须建立连接,效率会稍低

三、Socket/TCP

TCP报文

TCP报文是发送网络消息需要按照这种报文的格式去包装数据

一般需要了解一下几个字段:

  1. 序号:Seq序号,占32位,用来表示从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标识
  2. 确认序号:ACK序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ACK=Seq+1
  3. 标志位共六个:URG、ACK、PSH、RST、SYN、FIN含义:
    (1)URG:紧急指针
    (2)ACK :确认序号有效
    (3)PSH:接收方应该尽快将这个报文交给应用层
    (4)RST:充值连接
    (5)SYN:发起一个新连接
    (6)FIN:释放一个连接
  4. 需要注意的是:
    (A)不要将确认序号Ack与标志位中的ACK搞混了。
    (B)确认方Ack=发起方Req+1,两端配对

TCP三次握手

所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:

第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SEND状态,等待Server确认。
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ACK=J+1,随机产生一个seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RECV状态。
第三次握手:Client收到确认后,检查ACK是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ACK=K+1,并将数据包发送给Server,Server检查ACK是否为K+1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间就可以开始传输数据了。
SYN攻击:在三次握手过程中,Server发送SYN-ACK后,收到Client的ACK之前的TCP连接称为半连接,此时Serve处于SYN_RECV状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断的发送SYN包,Server回复确认包,并等待Client的确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络阻塞甚至系统瘫痪。SYN攻击就是一种典型的DDOS攻击,检测SYN攻击方式也很简单,即当有大量半连接状态且源地址是随机的,则可以断定遭到SYN攻击了,使用如下命令让其无处可逃:netstat -nap|grep SYN_RECV

TCP四次挥手

所谓四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总发送三个包以确认连接的断开。在Socket编程中,这一过程由客户端或服务端任一方执行close来触发,流程如下:

由于TCP连接是全双工的,因此每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传输,Client进入FIN_WAIT_1状态。
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传输,Server进入LAST_ACK状态
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手

四、Socket编程

(一)Socket编程方式

Socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开Open->读写write/read->关闭close”模式来操作文件。Socket就是该模式的一个实现,Socket即是一种特殊的文件,一些Socket函数就是对其进行操作(读写IO、打开、关闭)。因此Socket也提供了类似于连接Connect、关闭连接Close、发送、接收等方法的调用

(二)数据传输方式

常用stream和dgram

1. STREAM

表示面向连接的数据传输方式,数据可以准确无误地到达另一台计算机,如果丢失或损坏,可以重新发送,但是相对效率低

2.DGRAM

表示无连接的数据传输方式,计算机只管数据传输,不做数据校验,DGRAM所做的校验工作少,所以效率比STREAM高
例如:QQ视频聊天和语音聊天使用的就是DGRAM传输数据,因为首先需要保证通信的效率,尽量减少延迟,而数据的正确性是次要的,即使丢失很小的一部分数据视频和音频也可以正常解析,最多出现噪点或杂音,不会对通信质量有实质影响

(三)服务器端编写步骤

  1. 调用socket()函数创建一个用于通信的套接字
    买了个手机
  2. 给已经创建的套接字绑定一个端口号,一般通过设置网络套接口地址和调用bind()函数来实现
    办张手机卡,插上手机卡
  3. 调用listen()函数使套接字成为一个监听套接字
    等待来电
  4. 调用accept()函数来接受客户端的连接,这时就可以和客户端通信
    接听到了打来的电话
  5. 处理客户端的连接请求
    接通电话听、说沟通
  6. 终止连接
    挂断电话

(四)客户端编写步骤

  1. 调用socket()函数创建一个用于通信的套接字
    买了个手机
  2. 通过设置套接字地址结构,说明客户端与之通信的服务器的IP地址和端口号
    输入对方手机号
  3. 调用Connect()函数来建立与服务器的连接
    拨号,并等接听
  4. 调用读写函数发送或接收数据
    说话、听话
  5. 终止连接
    挂断电话

(五)案例

服务器端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;  //套接字的命名空间
using System.Net; //IPAddress的命名空间
using System.Threading; //线程的命名空间
namespace FrmServer
{public partial class 服务器 : Form{public 服务器(){InitializeComponent();toolStripStatusLabel1.Text = "服务器已关闭";}//1.1声明套接字Socket serverSocket = null;//3.2 创建用来专门作为监听来电等待工作的线程Thread listenThread = null;private void btnStartServer_Click(object sender, EventArgs e){if (btnStartServer.Tag.ToString() == "open"){btnStartServer.Tag = "close";btnStartServer.Text = "关闭服务器";//1.2调用Socket()函数 用于通信的套接字serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //第一个参数为寻找地址的方式,此时选定为IPV4的地址; 第二个参数为数据传输的方式,此时选择的是Stream传输(能够准确无误的将数据传输到);第三个参数为执行的协议,此时选择的是TCP协议;//2.套接字绑定端口号,设置套接字的地址调用bind()因为此函数需要EndPoint 所以创建2.1和2.2//2.1 设置地址  IPaddress 在using System.Net;下此时需引入IPAddress address = IPAddress.Parse(txtIP.Text.Trim());//2.2 设置地址和端口IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); //第一个参数为要设置的IP地址,第二参数为端口号try{//2.套接字绑定端口号和IPserverSocket.Bind(endPoint);toolStripStatusLabel1.Text = "服务已开启!";MessageBox.Show("开启服务成功", "开启服务");}catch (Exception ex){MessageBox.Show("开启服务失败:" + ex.Message, "开启服务失败");//ex.Message为出现异常的消息return;}//3.1监听套接字,等待serverSocket.Listen(10); //参数为最大监听的用户数listenThread = new Thread(ListenConnectSocket);listenThread.IsBackground = true; //关闭后天线程listenThread.Start();}else if (btnStartServer.Tag.ToString() == "close"){toolStripStatusLabel1.Text = "服务器已关闭";btnStartServer.Tag = "open";btnStartServer.Text = "开启服务器";isOpen = false;serverSocket.Close();serverSocket.Dispose();}}//3.3 用于判断用户是否链到服务器bool isOpen = true;  //3.4 监听用户来电 等待void ListenConnectSocket(){while (isOpen) {try{Socket ClientSocket = serverSocket.Accept();byte[] buffer = Encoding.Default.GetBytes("成功连接到服务器!");ClientSocket.Send(buffer); string client = ClientSocket.RemoteEndPoint.ToString();listBox1.Invoke(new Action<string>((msg) =>{listBox1.Items.Add(DateTime.Now + ": " + msg);}), client);Thread thr = new Thread(ReceiveCkientMsg);thr.IsBackground = true;thr.Start(ClientSocket);}catch (Exception ex){listenThread.Abort(ex.Message);}}}/// <summary>/// 服务器解释用户消息/// </summary>/// <param name="clientSocket"></param>private void ReceiveCkientMsg(object clientSocket){Socket client = clientSocket as Socket;while (true){byte[] recBuffer = new byte[1024 * 1024 * 2];int length = -1;try{length = client.Receive(recBuffer);}catch (Exception ex){string str = client.RemoteEndPoint.ToString();this.Invoke(new Action(() =>{listBox1.Items.Add($"{str}:{str}");listBox1.Items.Remove(str);}));break;}if (length==0){string str = client.RemoteEndPoint.ToString();this.Invoke(new Action(() =>{listBox1.Items.Add($"{str}:下线了!");listBox1.Items.Remove(str);}));break;}else{string msg = Encoding.Default.GetString(recBuffer,0, length);string msgStr = $"{DateTime.Now}【接收{client.RemoteEndPoint.ToString()}】{msg}";this.Invoke(new Action(() =>{txtReceive.AppendText(msgStr + Environment.NewLine);}));}}}}
}

客户端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace FrmClient
{public partial class Form1 : Form{public Form1(){InitializeComponent();}//1.1创建套接字Socket clientSocket = null;Thread clientThread = null;//连接服务器private void btnConnectStart_Click(object sender, EventArgs e){//1.2clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//地址类型,数据传输方式,协议//2.1 设置IP地址IPAddress address = IPAddress.Parse(txtIP.Text.Trim());//2.2 设置IP地址和端口号IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));try{txtRecive.AppendText("与服务器连接中..." + Environment.NewLine);//3与服务器建立连接clientSocket.Connect(endPoint); // 与服务器连接}catch (Exception ex){MessageBox.Show("连接失败:"+ex.Message,"友情提示");return;}txtRecive.AppendText("与服务器连接成功!" + Environment.NewLine);//4.接收或发送消息 使用线程来实现clientThread = new Thread(ReceiveMsg);clientThread.IsBackground = true; //开启后台线程clientThread.Start();}private void ReceiveMsg(){while (true){byte[] recBuffer = new byte[1024 * 1024 * 2];//声明最大字符内存int length = -1; //字节长度try{length = clientSocket.Receive(recBuffer);//返回接收到的实际的字节数量}catch (SocketException ex){break;}catch (Exception ex){this.Invoke(new Action(() =>{txtRecive.AppendText($"与服务器断开连接:{ex.Message}{Environment.NewLine}");}));break;}//接收到消息if (length>0){string msg = Encoding.Default.GetString(recBuffer, 0, length);//转译字符串(字符串,开始的索引,字符串长度)string str = $"{DateTime.Now}【接收】{msg}{Environment.NewLine}";//接收的时间,内容,换行this.Invoke(new Action(() =>{txtRecive.AppendText(str);//添加到文本}));}}}//发送消息private void btnSend_Click(object sender, EventArgs e){string str = txtSendBox.Text.Trim();byte[] buffer = Encoding.Default.GetBytes(str);clientSocket.Send(buffer);this.Invoke(new Action(() =>{txtRecive.AppendText($"{DateTime.Now}【发送】{str}{Environment.NewLine}");}));}  }
}

参考链接1
参考链接2

C#网络编程(Socket编程)相关推荐

  1. Java网络编程——Socket 编程

    Socket 编程 Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢.这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 我们可以发现Socket就在 ...

  2. Linux网络编程 | Socket编程(一):Socket的介绍、UDPSocket的封装、UDP服务器/客户端的实现

    目录 套接字编程 Sockaddr结构 字节序 地址转换 常用套接字接口 UDP的通信流程 UDPSocket的封装 UDP服务器 UDP客户端 套接字编程 所谓套接字(Socket),就是对网络中不 ...

  3. python网络编程-socket编程

    一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层模 ...

  4. [linux] Linux网络之Socket编程入门

    目录 1. 前言 2. 网络基础 2.1 协议 2.1.1 TCP和UDP协议 2.2 网络的层状结构 2.3 一台主机向另一台主机的发送数据的流向 2.4 IP和MAC地址 2.5 端口 2.6 网 ...

  5. 初识网络及socket编程基础

    理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址. 源ip地址就是发送端ip,目的ip地址就是接收端ip 思考: 我们光有IP地址就可以完成通 ...

  6. 网络基础+Socket编程+高并发服务器

    网络编程 P1 复习 Linux 网络编程 P2 信号量生产者复习 P3 协议 P4 七层模型和四层模型及代表协议 P5 网络传输数据封装流程 P6 以太网帧和ARP请求 P7 IP 协议 P8 TC ...

  7. Linux网络编程——socket编程

    一.socket socket 网络套接字一个文件文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现(接收缓冲区和发送缓冲区))通讯过程中,套接字一定是 [成对] 出现的. 二.网络字节序 ...

  8. Day8 - Python网络编程 Socket编程 --转自金角大王

    本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实 ...

  9. iOS开发 网络编程 Socket编程

    一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程 ...

  10. Linux网络编程 | Socket编程(二)TCPSocket的封装、TCP服务器多进程、多线程版本的实现

    目录 TCP的通信流程 TCPSocket的封装 TCP客户端 TCP服务器 多进程版本 多线程版本 TCP的通信流程 计算机网络 (三) 传输层 :一文搞懂UDP与TCP协议 在这篇博客中,我描述了 ...

最新文章

  1. js获取当前系统时间
  2. oracle表空间dbf文件,Oracle 11g表空间dbf文件迁移
  3. Linux下对于inode的理解
  4. ITK:遮罩图像的归一化相关性
  5. c语言条件编译的例子,C语言条件编译分析实例
  6. AutoPep8-----Pycharm自动排版工具
  7. mysql out_mysql存储过程 in out inout
  8. pow计算x的y次方
  9. 三十天学不会TCP,UDP/IP网络编程-IP头格式祥述
  10. (保姆级)Oracle的下载及安装详细教程
  11. Chrome浏览器查看Axure原型图文件,提示Axure RP Extension for Chrome
  12. 3W咖啡商业计划书模板
  13. 计算机组成与设计第五版课后答案ch04,数据结构第4章例题与答案
  14. 银行账户模拟java_使用Java模拟银行账户存、取款、转账功能
  15. EC2实例挂载使用EFS操作步骤
  16. STM32 f103搭配LM386声音传感器实现简单音乐识别
  17. 《东周列国志》第四十三回 智宁俞假鸩复卫 老烛武缒城说秦
  18. AI绘画正在取代设计师?答案是这样的
  19. RT_Thread_进程间通讯——邮箱
  20. PS批量处理图片尺寸

热门文章

  1. JQuery文档分析1-JQuery核心与选择器
  2. mysql安装包如何使用_关于MySQL安装包如何使用的详细介绍
  3. python初级樱花编程代码_python turtle绘制樱花树代码
  4. html5+JS调用手机摄像头扫码
  5. iOS开发人员需要了解的苹果开发者账号与邓白氏编码
  6. Java拦截器实现拦截controller方法
  7. linux下JMeter安装
  8. 怎样制作动图gif?GIF生成器帮你一键制作gif
  9. linux如何入侵电脑,如何入侵Linux系统 -电脑资料
  10. linux zip命令安装,linux安装zip命令