该博客源著地址https://www.cnblogs.com/sunev/archive/2012/08/05/2604189.html

一、摘要

  总结一下基于C#的TCP传输协议的涉及到的常用方法及同步实现。

二、实验平台

  Visual Studio 2010

三、socket编程的一些常用方法(同步实现)

3.1 命名空间

  需要添加的命名空间

  1. using System.Net;
  2. using System.Net.Socket;

3.2 构造新的socket对象

socket原型:

  1. public socket (AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)

(1) AddressFamily 用来指定socket解析地址的寻址方案,Inte.Network标示需要ip版本4的地址,Inte.NetworkV6需要ip版本6的地址;

(2) SocketType 参数指定socket类型,Raw支持基础传输协议访问,Stream支持可靠,双向,基于连接的数据流;

(3) ProtocolType 表示socket支持的网络协议,如常用的TCP和UDP协议。

3.3 定义主机对象
(1) IPEndPoint类

原型:

a)

  1. public IPEndPoint(IPAddress address,int port)

参数address可以直接填写主机的IP,如"192.168.2.1";

b)

  1. public IPEndPoint(long address,int port)

参数address整型int64如123456,参数port端口int32,如6655。

(2) 利用DNS服务器解析主机,使用Dns.Resolve方法

原型:

  1. public static IPHostEntry Resolve(string hostname)

参数:待解析的主机名称,返回IPHostEntry类值,IPHostEntry为Inte.Net主机地址信息提供容器,该容器提供存有IP地址列表,主机名称等。

(3) Dns.GetHostByName获取本地主机名称

原型:

  1. public static IPHostEntry GetHostByName(string hostname)

(4) GetHostByAddress

原型:

a)

  1. public static IPHostEntry GetHostByAddress(IPAddress address)

参数:IP地址。

b)

  1. public static IPHostEntry GetHostByAddress(string address)

参数:IP地址格式化字符串。

3.4 端口绑定和监听

  同步套接字服务器主机的绑定和端口监听,Socket类的Bind(绑定主机),Listen(监听端口),Accept(接收客户端的连接请求)。

(1) Bind

原型:

  1. public void Bind(EndPoint LocalEP)

参数为主机对象 IPEndPoint

(2) Listen

原型:

  1. public void Listen(int backlog)

参数整型数值,挂起队列最大值

(3) accept

原型:

  1. public socket accept()

返回为套接字对象

3.5 socket的发送和接收方法

(1) 发送数据

a)socket类的send方法

原型一:

  1. public int Send(byte[] buffer)

参数:待发送的字节数组;

原型二:

  1. public int Send(byte[],SocketFlags)

SocketFlags成员列表:

DontRoute不使用路由表发送,

MaxIOVectorLength为发送和接收数据的wsabuf结构数量提供标准值,

None 不对次调用使用标志,

OutOfBand消息的部分发送或接收,

Partial消息的部分发送或接收,

Peek查看传入的消息。

原型三:

  1. public int Send(byte[],int,SocketFlags)

参数二要发送的字节数

原型四:

  1. public int Send(byte[],int,int,SocketFlags)

参数二为Byte[]中开始发送的位置

b) NetWordStream类的Write方法

原型:

  1. public override void write(byte[] buffer,int offset,int size)

参数分别为:字节数组,开始字节位置,总字节数。

(2) 接收数据

a) Socket类Receive方法

原型一:

  1. public int Receive(byte[] buffer) 

原型二:

  1. public int Receive(byte[],SocketFlags)

原型三:

  1. public int Receive(byte[],int,SocketFlags)

原型四:

  1. public int Receive(byte[],int,int,SocketFlags)

Socket类Receive方法的相关参数可参看Socket类Send方法中的参数。

b) NetworkStream类的Read方法

  1. public override int Read(int byte[] buffer,int offset,int size)

参数可参看NetworkStream类的Write方法。

四、TCP传输协议的同步实现

4.1 服务器端编程的步骤:

(1) 创建套接字;

(2) 绑定套接字到一个IP地址和一个端口上(bind());

(3)将套接字设置为监听模式等待连接请求(listen());

(4)请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());

(5)用返回的套接字和客户端进行通信(send()/recv());

(6)返回,等待另一连接请求;

(7)关闭套接字。

服务器端代码:

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Collections.Generic;
  5. using System.Text;
  6.  
  7. namespace net
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. //定义接收数据长度变量
  14. int recv;
  15. //定义接收数据的缓存
  16. byte[] data = new byte[1024];
  17. //定义侦听端口
  18. IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5566);
  19. //定义套接字类型
  20. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  21. //连接
  22. socket.Bind(ipEnd);
  23. //开始侦听
  24. socket.Listen(10);
  25. //控制台输出侦听状态
  26. Console.Write("Waiting for a client");
  27. //一旦接受连接,创建一个客户端
  28. Socket client = socket.Accept();
  29. //获取客户端的IP和端口
  30. IPEndPoint ipEndClient = (IPEndPoint)client.RemoteEndPoint;
  31. //输出客户端的IP和端口
  32. Console.Write("Connect with {0} at port {1}", ipEndClient.Address, ipEndClient.Port);
  33. //定义待发送字符
  34. string welcome = "Welcome to my server";
  35. //数据类型转换
  36. data = Encoding.ASCII.GetBytes(welcome);
  37. //发送
  38. client.Send(data, data.Length, SocketFlags.None);
  39. while (true)
  40. {
  41. //对data清零
  42. data = new byte[1024];
  43. //获取收到的数据的长度
  44. recv = client.Receive(data);
  45. //如果收到的数据长度为0,则退出
  46. if (recv == 0)
  47. break;
  48. //输出接收到的数据
  49. Console.Write(Encoding.ASCII.GetString(data, 0, recv));
  50. //将接收到的数据再发送出去
  51. client.Send(data, recv, SocketFlags.None);
  52. }
  53. Console.Write("Disconnect form{0}", ipEndClient.Address);
  54. client.Close();
  55. socket.Close();
  56. }
  57. }
  58. }

4.2 客户端编程的步骤:

(1) 创建套接字;

(2) 向服务器发出连接请求(connect());

(3) 和服务器端进行通信(send()/recv());

(4) 关闭套接字。

客户端代码:

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Collections.Generic;
  5. using System.Text;
  6.  
  7. namespace client
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. //定义发送数据缓存
  14. byte[] data = new byte[1024];
  15. //定义字符串,用于控制台输出或输入
  16. string input, stringData;
  17. //定义主机的IP及端口
  18. IPAddress ip = IPAddress.Parse("127.0.0.1");
  19. IPEndPoint ipEnd = new IPEndPoint(ip, 5566);
  20. //定义套接字类型
  21. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  22. //尝试连接
  23. try
  24. {
  25. socket.Connect(ipEnd);
  26. }
  27. //异常处理
  28. catch (SocketException e)
  29. {
  30. Console.Write("Fail to connect server");
  31. Console.Write(e.ToString());
  32. return;
  33. }
  34. //定义接收数据的长度
  35. int recv = socket.Receive(data);
  36. //将接收的数据转换成字符串
  37. stringData = Encoding.ASCII.GetString(data, 0, recv);
  38. //控制台输出接收到的数据
  39. Console.Write(stringData);
  40.  
  41. //定义从键盘接收到的字符串
  42. input = Console.ReadLine();
  43.  
  44. //将从键盘获取的字符串转换成整型数据并存储在数组中
  45. data = Encoding.ASCII.GetBytes(input);
  46. //发送该数组
  47. socket.Send(data, data.Length, SocketFlags.None);
  48.  
  49. while (true)
  50. {
  51. //
  52.  
  53. //如果字符串是"exit",退出while循环
  54. if (input == "exit")
  55. {
  56. break;
  57. }
  58. //对data清零
  59. data = new byte[1024];
  60. //定义接收到的数据的长度
  61. recv = socket.Receive(data);
  62. //将接收到的数据转换为字符串
  63. stringData = Encoding.ASCII.GetString(data, 0, recv);
  64. //控制台输出字符串
  65. Console.Write(stringData);
  66. //发送收到的数据
  67. socket.Send(data, recv, 0);
  68.  
  69. }
  70. Console.Write("disconnect from server");
  71. socket.Shutdown(SocketShutdown.Both);
  72. socket.Close();
  73. }
  74.  
  75. }
  76. }

  上述代码实现了,当连接建立之后,客户端向服务器端发送键盘输入的字符,服务器端收到字符后,显示在控制台并发送给客户端,客户端收到字符后,显示在控制台并再次发送给服务器端,如此循环。

五、实验结果

  先后运行服务器端程序和客户端程序,控制台界面如下:

图1 服务器端控制台

  当连接建立后,服务器端控制台显示等待客户端的状态"Waiting for a client",并打印出连接信息。

图2 客户端控制台

  当连接建立后,客户端收到来自服务器端发送的字符串"Welcome to my server"。

  之后,客户端通过键盘发送数据,二者循环接收并发送,控制台分别如下:

图3 服务器控制台

图4 客户端控制台

六、几点说明

6.1 传输速度

  (1) 增大发送和接收的数组可提升传输速度,即增加一次实际发送数据的数量可以提高传输速度,但数组中数据的个数也不能一味的增大。需要说明的,由于地层MIT的限制,底层具体实现的时候每次发送的数据仍是不超过1510个的。

  (2) 将控制台界面最小化后,速度也会有翻倍的提升。

6.2 MFC的转换

  为了使传输协议更有可观性和使用性,通常做成MFC的样式,具体的使用已在"基于TCP协议的网络摄像头的设计与实现"应用。

基于C#的socket编程的TCP同步实现的更多相关文章

  1. 基于C#的socket编程的TCP异步实现

    一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...

  2. (转)基于C#的socket编程的TCP异步实现

    一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...

  3. 计算机网络(十三),Socket编程实现TCP和UDP

    十三.Socket编程实现TCP和UDP 1.TCP (1)TCPServer.java类 package com.interview.javabasic.socket; import com.int ...

  4. 基于MFC的socket编程(异步非阻塞通信)

       对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...

  5. 基于win32的socket编程及程序实现

    初步研究了win32平台的Windows Sockets,它是Microsoft Windows的网络程序设计接口,它是从Berkeley Sockets扩展而来的,以动态链接库的形式提供给我们使用. ...

  6. socket编程实现tcp服务器_C/C++

    1. 需求分析 实现一个回声服务器的C/S(客户端client/服务器server)程序,功能为客户端连接到服务器后,发送一串字符串,服务器接受信息后,返回对应字符串的大写形式给客户端显示. 例如: ...

  7. day8---多线程socket 编程,tcp粘包处理

    复习下socket 编程的步骤: 服务端:   1 声明socket 实例 server = socket.socket()  #括号里不写  默认地址簇使用AF_INET  即 IPv4       ...

  8. 基于java的socket编程

    #开头的废话#学习java已经半个月了,原本在抠教材里面的字眼时,觉得教材好厚,要看完不知道要到猴年马月去了.突然在网上看到一个教程,里面老师说学编程语言书不用太细看,看个大概,知道里面讲些什么就好, ...

  9. 基于MFC的socket编程

    网络编程 1.windows 套接字编程(开放的网络编程接口)添加头文件#include<windows.h> 2.套接字及其分类 socket分为两种:(1)数据报socket:无连接套 ...

随机推荐

  1. 通过Cloudflare开启全站https

    Cloudflare 添加域名后,会自动生成通用证书,快速开启全站HTTPS,服务端不用做任何修改,还可以选择多种开启模式 一.注册Cloudflare账号 直接打开网站:https://www.cl ...

  2. Java集合详解(五):Hashtable原理解析

    概述 本文是基于jdk8_271版本进行分析的. Hashtable与HashMap一样,是一个存储key-value的双列集合.底层是基于数组+链表实现的,没有红黑树结构.Hashtable默认初始 ...

  3. Qt - QLineEdit编辑框

    QLineEdit输入内容获取及合理性检查? 控件自带触发信息: void textChanged(const QString &);void textEdited(const QString ...

  4. RHCE脚本题目详解

    目录 RHCE脚本题目详解 题目一 shell脚本之if语句实现: shell脚本之case语句实现: 题目二 实现 测试 解析 写在后面 RHCE脚本题目详解 题目一 在system1上创建一个名为 ...

  5. cento 7使用minicom串口调试工具

    cento 7使用minicom串口调试工具   因为要使用串口配置设备,所以考虑要用串口管理软件,windows下比较容易了,直接用超级终端也好,用CRT也可以,CentOS系统稍微麻烦一点,前几天 ...

  6. ipmitool -I lanplus -H IPADDR -U USERNAME -P PASSWORD power reset

    IPMI是智能型平台管理接口(Intelligent Platform Management Interface)的缩写,是管理基于 Intel结构的企业系统中所使用的外围设备采用的一种工业标准,该标 ...

  7. Linux_配置辅助DNS服务(基础)

    [RHEL8]-DNSserver1:[RHEL7]-DNSserver2:[Centos7]-DNSclient !!!测试环境我们首关闭防火墙和selinux(DNSserver1.DNSserv ...

  8. python基础之字符串类型

    一.python字符串类型概述 定义:在单引号\双引号\三引号内,由一串字符组成 name='Test' name = 'test' print(type(name)) --------------- ...

  9. IDEA 查看类图功能(分析源码的利器)

    引言 做过项目开发的童靴,应该会有这样的经历,就是刚进公司领导二话不说直接丢个项目,而且没有任何文档,让熟悉一下,一两周就让上手写代码.打开项目后就看到一堆类源码,完全不知道从何处入手,应该如何分析项 ...

  10. S5 Linux信息显示与搜索文件命令

    5.1-5 uname.hostname.dmesg.stat.du 5.6 date:显示与设置系统时间 5.7 echo:显示一行文本 5.8-12 watch.which.whereis.loc ...