TCP/IP 体系结构与特点
    TCP/IP协议实际上就是在物理网上的一组完整的网络协议。其中TCP是提供传输层服务,而IP则是提供网络层服务。TCP/IP包括以下协议:

    IP:网间协议(Internet Protocol) 负责主机间数据的路由和网络上数据的存储。同时为ICMP,TCP,UDP提供分组发送服务。用户进程通常不需要涉及这一层。
  ARP:地址解析协议(Address Resolution Protocol)
   此协议将网络地址映射到硬件地址。
  RARP:反向地址解析协议(Reverse Address Resolution Protocol)
   此协议将硬件地址映射到网络地址
  ICMP:网间报文控制协议(Internet Control Message Protocol)
   此协议处理信关和主机的差错和传送控制。
  TCP:传送控制协议(Transmission Control Protocol)
   这是一种提供给用户进程的可靠的全双工字节流面向连接的协议。它要为用户进程提供虚电路服务,并为数据可靠传输建立检查。(注:大多数网络用户程序使用TCP)
  UDP:用户数据报协议(User Datagram Protocol)
   这是提供给用户进程的无连接协议,用于传送数据而不执行正确性检查。
  FTP:文件传输协议(File Transfer Protocol)
   允许用户以文件操作的方式(文件的增、删、改、查、传送等)与另一主机相互通信。
  SMTP:简单邮件传送协议(Simple Mail Transfer Protocol)
   SMTP协议为系统之间传送电子邮件。
  TELNET:终端协议(Telnet Terminal Procotol)
   允许用户以虚终端方式访问远程主机
  HTTP:超文本传输协议(Hypertext Transfer Procotol)  
  TFTP: 简单文件传输协议(Trivial File Transfer Protocol)
    TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。因此用户一般不涉及。 编程时,编程界面有两种形式:一、是由内核心直接提供的系统调用;二、使用以库函数方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过 核外的应用程序才能实现,所以要

使用套接字(socket)来实现。


套接字基本概念:
    套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个 网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数 据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。各种进程使用这个相同的域互相之间用Internet协议簇来进行通信。
    套接字可以根据通信性质分类,这种性质对于用户是可见的。应用程序一般仅在同一类的套接字间进行通信。不过只要底层的通信协议允许,不同类型的套接字间也照样可以通信。套接字有两种不同的类型:流套接字和数据报套接字。
    (1)流式套接字(SOCK_STREAM):一种面向连接的Socket,针对于面向连接的TCP服务应用;
  (2)数据报式套接字(SOCK_DGRAM):一种无连接的Socket,对应于无连接的UDP服务应用。
   从用户的角度来看,SOCK_STREAM、SOCK_DGRAM这两类套接字似乎的确涵盖了TCP/IP应用的全部,因为基于TCP/IP的应用,从 协议栈的层次上讲,在传输层的确只可能建立于TCP或UDP协议之上,而SOCK_STREAM、SOCK_DGRAM又分别对应于TCP和UDP,所以 几乎所有的应用都可以用这两类套接字实现。


套接字工作原理
    要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。
    根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
    所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
    所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
    所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述 发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
典型过程图
面向连接的套接字的系统调用时序图

无连接协议的套接字调用时序图

C#实现套接字编程的实例――聊天室程序
    本程序是基于C/S(服务器/客户端)构架的,程序包含一个服务器端的应用程序和一个客户端的应用程序。
    首先,在服务器上运行服务器端的应用程序,该程序一运行就开始服务器监听。
    然后,在客户机上就可以打开客户端的应用程序。程序打开后可以与服务器端应用程序进行连接,即进行客户端请求。在连接确认后,客户端用户可以和其他的客户端用户进行聊天。客户端人数没有限制,同时还支持“悄悄话”聊天模式,支持聊天记录。
    所以这是一个学习套接字编程的相当不错的例子。而且,程序中为了处理每个客户端的信息还用到了多线程机制。在每个客户端与服务器端连接成功后,它们之间就建立一个线程。这样运用了多线程之后,客户端之间就不会相互影响,即使其中一个出了错误也不会影响到另一个。
服务器端程序:
    布置界面。只需在界面上添加一个ListBox控件即可,该控件主要用于显示客户端的用户的一些信息的。
服务器端程序的代码编写:
    对于服务器端,主要的作用是监听客户端的连接请求并确认其请求。程序一开始便打开一个StartListening()线程。
    开始定义如下变量:
private System.Net.Sockets.TcpListener theListener;
private System.Net.Sockets.Socket clientSocket;
private System.Threading.Thread clientService;
StartListening()函数如下:
private void StartListening()
{
  theListener = new System.Net.Sockets.TcpListener(listenPort); //listenPort为端口号
  theListener.Start();
  while (true)
  {
       try
       {
          System.Net.Sockets.Socket s = theListener.AcceptSocket();
          clientSocket = s;
          clientService = new System.Threading.Thread(new System.Threading.ThreadStart(ServiceClient));
          clientService.Start();
       }
       catch(Exception e)
       {
          Console.WriteLine(e.ToString() );
       }
  }
}
    该线程是一直处于运行状态的。
    当服务器端接收到一个来自客户端的连接请求后,它就打开一个ServiceClient()线程来服务客户端。当一个连接被建立后,每个客户端就被赋予一个属于它自己的套接字。同时,一个Client类的对象被建立。该对象包含了客户端的一些相关信息,该信息被保存在一个数组列表中。
Client类如下:
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace ChatServer
{
    public class Client
    {
        private Thread clientThread;
        private EndPoint theEndPoint;
        private string name;
        private Socket sock;
        public Client(string _name, EndPoint _endpoint, Thread _thread, Socket _sock)
        {
            clientThread = _thread;
            theEndpoint = _endpoint;
            name = _name;
            sock = _sock;
        }
        public override string ToString()
        {
            return TheEndpoint.ToString()+ " : " + name;
        }
        public Thread CLThread
        {
            get{return clientThread;}
            set{clientThread = value;}
        }
        public EndPoint Host
        {
            get{return theEndpoint;}
            set{theEndpoint = value;}
        }
        public string TheName
        {
            get{return name;}
            set{name = value;}
        }
        public Socket TheSock
        {
            get{return sock;}
            set{sock = value;}
        }
    }
}
    程序的主体部分应是ServiceClient()函数。该函数是一个独立的线程,其主要部分是一个while循环。在循环体内,程序处理各种客户端命令。
    服务器端接收来自客户端的以ASCII码给出的字符串,其中包含了一个"|"形式的分隔符。
    字符串中"|"以前的部分就是具体的命令,包括CONN、CHAT、PRIV、GONE四种类型。
    CONN命令建立一个新的客户端连接,将现有的用户列表发送给新用户并告知其他用户有一个新用户加入。
    CHAT命令将新的信息发送给所有用户。
    PRIV命令将悄悄话发送给某个用户。
    GONE命令从用户列表中除去一个已离开的用户并告知其他的用户某某已经离开了。同时,GONE命令可以设置布尔型的变量keepAlive为false从而结束与客户端连接的线程。
ServiceClient()函数如下:
private void ServiceClient()
{
    System.Net.Sockets.Socket clientS = clientSocket;
    bool keepAlive = true;
    while (keepAlive)
    {
        Byte[] buffer = new Byte[1024];
        clientS.Receive(buffer);
        string clientCommand = System.Text.Encoding.ASCII.GetString(buffer);
        string[] tokens = clientCommand.Split(new Char[]{'|'});
        Console.WriteLine(clientCommand);
        if (tokens[0] == "CONN")
        {
            for(int n=0; n<clients.Count;n++)
            {
                Client cl = (Client)clients[n];
                SendToClient(cl, "JOIN|" + tokens[1]);
            }
            System.Net.EndPoint ep = clientS.RemoteEndPoint;
            Client c = new Client(tokens[1], ep, clientService, clientS);
            clients.Add(c);
            string message = "LIST|" + GetChatterList() +"\r\n";
            SendToClient(c, message);
            lbClients.Items.Add(c);
        }
        if (tokens[0] == "CHAT")
        {
            for(int n=0; n<clients.Count;n++)
            {
                Client cl = (Client)clients[n];
                SendToClient(cl, clientCommand);
            }
        }
        if (tokens[0] == "PRIV")
        {
            string destClient = tokens[3];
            for(int n=0; n<clients.Count;n++)
            {
                Client cl = (Client)clients[n];
                if(cl.Name.CompareTo(tokens[3]) == 0)
                    SendToClient(cl, clientCommand);
                if(cl.Name.CompareTo(tokens[1]) == 0)
                    SendToClient(cl, clientCommand);
            }
        }
        if (tokens[0] == "GONE")
        {
            int remove = 0;
            bool found = false;
            int c = clients.Count;
            for(int n=0; n<clients.Count;n++)
            {
                Client cl = (Client)clients[n];
                SendToClient(cl, clientCommand);
                if(cl.Name.CompareTo(tokens[1]) == 0)
                {
                    remove = n;
                    found = true;
                    lbClients.Items.Remove(cl);
                }
            }
            if(found)
                clients.RemoveAt(remove);
            clientS.Close();
            keepAlive = false;

}
    }
}
这样,服务器端程序就基本完成了。

C#中的套接字编程(一) --转相关推荐

  1. 浅析C#中的套接字编程

    套接字基本概念: 套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面.套接字存在于通信域中 ...

  2. 什么是Python中的套接字编程?

    摘要:本文涵盖了有关使用Python进行套接字编程的所有领域.套接字可以帮助您建立这些连接,而Python无疑可以简化连接. 本文分享自华为云社区<从零开始学python | 什么是Python ...

  3. Python中的套接字编程

    文章目录 **连接到服务器:** **一个简单的服务器客户端程序:** **服务器** **客户端** 套接字编程是一种连接网络上的两个节点以相互通信的方法.一个套接字(节点)侦听 IP 处的特定端口 ...

  4. C#中的套接字编程(二) --转

    客户端程序的代码编写:     布置界面.往界面上添加一个ListBox控件(用于显示用户列表),一个RichTextBox控件(用于显示聊天消息以及系统消息),一个 TextBox控件(用于发送消息 ...

  5. java套接字编程_Java套接字编程:教程

    java套接字编程 本教程是Java套接字编程的简介,从一个简单的客户机-服务器示例开始,该示例演示了Java I / O的基本功能. 将向您介绍原始的java.io软件包和NIO,即Java 1.4 ...

  6. python中typeerror怎么解决_Python 3中套接字编程中遇到TypeError: 'str' does not support the buffer interface的解决办法...

    目前正在学习python,使用的工具为python3.2.3.发现3x版本和2x版本有些差异,在套接字编程时,困扰了我很久,先将python核心编程书中的例子 代码如下: 服务器端: #Echo se ...

  7. 套接字编程---2(TCP套接字编程的流程,TCP套接字编程中的接口函数,TCP套接字的实现,TCP套接字出现的问题,TCP套接字多进程版本,TCP套接字多线程版本)

    TCP模型创建流程图 TCP套接字编程中的接口 socket 函数 #include <sys/types.h> /* See NOTES */ #include <sys/sock ...

  8. Linux 套接字编程中的 5 个隐患

    Linux 套接字编程中的 5 个隐患 (2011-05-03 17:50) 分类: Socket编程 在 4.2 BSD UNIX® 操作系统中首次引入,Sockets API 现在是任何操作系统的 ...

  9. 原始套接字编程”中的Teardrop代码编程

    原始套接字编程"中的Teardrop代码编程 (1)实验代码: #include <stdio.h> #include <stdlib.h> #include < ...

最新文章

  1. 《浪潮之巅》读书笔记汇总
  2. 20162328蔡文琛week07
  3. 设计模式复习-享元模式
  4. Python 库升级问题-module ‘requests.exceptions‘ has no attribute ‘ReadTimeout‘原因及解决办法
  5. [BUUCTF-pwn]——picoctf_2018_can_you_gets_me
  6. python半年能达到什么程度_花半年的时间能把Python自学到什么程度?
  7. 运行多个 npm script 的各种姿势
  8. Spring MVC 无XML配置入门示例
  9. Linux一行代码修改时区
  10. Cordova用插件时注意事项,不然,插件调用不到!
  11. Android记录日志方式,关于Android中处理崩溃异常和记录日志的另一种实现思路
  12. html网页静态时钟代码,网页时钟实现代码html5
  13. SiT3373:220 -725MHz 低抖动压控差分振荡器VCXO
  14. win7、win10系统双屏显示任务栏
  15. [LOJ6515]「雅礼集训 2018 Day10」贪玩蓝月
  16. 它来了它来了!2020深度学习硬核技术干货集锦!
  17. 南邮 OJ 1484 烧饼重叠问题
  18. linux怎么打开pak文件怎么打开,如何在 Linux 上安装并启用 Flatpak 支持?
  19. GUI 图形用户界面编程实例-记事本的设计
  20. [每日100问][2011-9-06]iphone开发笔记,今天你肿了么

热门文章

  1. ASP.NET MVC 4 视图页去哪里儿
  2. 与众不同 windows phone (36) - 8.0 新的瓷贴: FlipTile, CycleTile, IconicTile
  3. SCCM 2007 R2 报表问题(二)
  4. Android开发中的logcat工具使用方法
  5. NI Vision for LabVIEW 基础(二):准备测量图像
  6. 【WPF】一个类似于QQ面板的GroupShelf控件
  7. 容器编排技术 -- Kubernetes 给容器和Pod分配CPU资源
  8. ubuntu14.04修改limits.conf后链接限制仍然不生效
  9. ZooKeeper程序员指南--使用ZooKeeper开发分布式应用程序
  10. maccmsv10 苹果cms10 站群扩展 自用版