一  Socket简介

  1. Socket翻译过来是套接字,具体含义可自行百度,简言之就是IP:Port的组合,是网络通信的一个窗口,IP就是地址和门牌号(比如长沙市韶山北路81号),Port就是房间号(比如6楼611室)。
  2. Visual Studio(简称VS)中System.Net.Sockets命名空间就是提供Socket网络应用的相关类的,其中Socket类、TcpClient类、TcpServer类、TcpListener类较为常用,是实现Socket网络通信必备的。至于“命名空间”、“类”等术语限于篇幅请自行百度。
  3. 我们常用的SocketTool.exe就是用Socket技术实现的。
  4. Socket之间的通信可以类比生活中打电话的案例。任何用户在通话之前,首先要占有一部电话机,相当于申请一个Socket,同时要知道对方的号码,相当于对方有一个固定的Socket,然后向对方拨号呼叫,相当于发出连接请求。假如对方在场并空闲,拿起 电话话筒,双方就可以进行通话了。双方的通话过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机,相当于关闭socket,撤销连接。
  5. Socket不仅可以在两台电脑之间通信,还可以在同一台电脑上的两个程序间通信。

二  Socket一般应用模式

Socket一般应用模式即:客户端、服务器模式

服务器端侦听一般会打开至少两个Socket

01.一个负责接收客户端连接请求(但不负责与客户端通信)
02.每成功接收到客户端的连接便在服务器端产生一个与之对应的通信的Socket,该Socket是在接收到客户端连接时就会创建的,为每个连接成功的客户端请求在服务器端都创建一个对应的Socket(负责和客户端通信)

客户端的Socket

01.必须指定要连接的服务器地址和端口
02.通过创建一个Socket对象来初始化一个到服务器端的TCP连接

下面是一张服务器、客户端Socket通信的原理图

下面我们来看下Socket更具体的通信过程:
  服务器端:
    01,申请一个socket
    02,绑定到一个IP地址和一个端口上
    03,开启侦听,等待接收连接

客户端:
    01,申请一个socket
    02,指定要连接的服务器(指明服务器的IP地址和端口号)

服务器端:

01.接收到连接请求后,产生一个新的socket(端口大于1024)与客户端建立连接并进行通信(就相当于公司的前台)

02.原监听socket继续监听。

注意:负责通信的Socket不能无限创建,创建的数量和操作系统有关。

2.1  Socket构造函数

Socket的构造函数
    Public Socket(AddressFamily addressFamily,SocketType  socketType,ProtocolType  protocolTYpe)
各参数的含义:

AddressFamily:指定Socket用来解析地址的寻址方案
   SocketType:定义要打开的Socket的类型
   Socket类使用ProtocolType枚举向Windows  Sockets  API通知所请求的协议

注意:
   1,端口号必须在 1 和 65535之间,最好在1024以后(1024以内的端口一般都是系统定义的端口,最好不要占用)。
   2,要连接的远程主机必须正在监听指定端口,也就是说你无法随意连接远程主机。

如:
IPAddress addr = IPAddress.Parse(“192.168.1.118″);
IPEndPoint endp = new IPEndPoint(addr,9000);
         服务端先绑定:serverSocket.Bind(endp)
         客户端再连接:clientSocket.Connect(endp)

3,一个客户端Socket一次只能连接一台主机(服务器端)
   4,Socket关闭后无法再次使用
   5,每个Socket对象只能与一台远程主机连接。如果你想连接到多台远程主机,你必须创建多个Socket对象。

2.2  Socket常用类和方法

相关类:

IPAddress:包含了一个IP地址
   IPEndPoint:包含了一对IP地址和端口号

方法:
   Socket():创建一个Socket
   Bind():绑定一个本地的IP和端口号(IPEndPoint)
   Listen():让Socket侦听传入的连接(俗称:等待上线),并指定侦听队列容量
   Connect():初始化与另一个Socket的连接
   Accept():接收连接并返回一个新的Socket
   Send():输出数据到Socket
   Receive():从Socket中读取数据
   Close():关闭Socket,销毁连接

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ASimpleSocketComm
{
    public partial class frm_Server : Form
    {
        public frm_Server()
        {
            InitializeComponent();
        }

        //窗体加载事件
        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        //开始侦听 按钮单击事件
        private void btn_StartLsn_Click(object sender, EventArgs e)
        {
            //获取输入框中的IP地址
            IPAddress myip = IPAddress.Parse(txt_IP.Text);

            //获取输入框中的端口号
            int myport = int.Parse(txt_Port.Text);

            //构建IP终结点
            IPEndPoint ippoint = new IPEndPoint(myip, myport);

            //创建监听用的Socket
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //解释:第一个参数代表使用IPV4寻址方案,第二个参数是指采用Stream方式进行通信,第三个参数是指基于TCP协议

            try
            {
                //将创建好的socket绑定到具体的IP终结点
                socket.Bind(ippoint);

                //同一时间最多接收10个客户端上线,多余的需排队
                socket.Listen();

                //在Server窗体中显示信息
                txt_SrvMsg.AppendText("服务器开始侦听...\r\n");

                Thread mythread = new Thread(AcceptInfo);
                mythread.IsBackground = true;
                mythread.Start(socket);
            }
            catch (Exception ex)
            {
                txt_SrvMsg.AppendText(ex.Message + "\r\n");
            }
        }

        //记录通信用的Socket
        Dictionary<string, Socket> dic = new Dictionary<string, Socket>();

        //侦听并接收客户端上线连接
        void AcceptInfo(object o)
        {
            Socket socket = o as Socket;

            //循环接收消息 死循环
            while (true)
            {
                try
                {
                    //创建通信用的socket
                    Socket tScocket = socket.Accept();
                    string ippoit = tScocket.RemoteEndPoint.ToString();

                    txt_SrvMsg.AppendText(ippoit + "连接成功!\r\n");
                    dic.Add(ippoit, tScocket);//将连接上来的客户端IPPORT保存到dic中
                    cbx_IPEndPoint.Items.Add(ippoit);//将连接上来的客户端IPPORT添加到下拉框中

                    //接收消息
                    Thread th = new Thread(ReceiveMsg);
                    th.IsBackground = true;
                    th.Start(tScocket);
                }
                catch (Exception ex)
                {
                    txt_SrvMsg.AppendText(ex.Message + "\r\n");
                    break;
                }
            }
        }

        //接收客户端发送的消息
        void ReceiveMsg(object o)
        {
            Socket client = o as Socket;
            while (true)
            {
                //接收客户端发送过来的数据
                try
                {
                    //定义byte数组存放从客户端接收到的数据
                     * ];

                    //将接收的数据放入buffer中,并返回实际接收数据的长度
                    int n = client.Receive(buffer);

                    //将字节数组转换成字符串
                    , n);

                    //将接收的数据显示到Server窗体中
                    txt_SrvMsg.AppendText(client.RemoteEndPoint.ToString() + ":" + words + "\r\n");
                }
                catch (Exception ex)
                {
                    txt_SrvMsg.AppendText(ex.Message + "\r\n");
                    break;
                }
            }
        }

        //给客户端发送消息 发送消息按钮单击事件
        private void btn_SendMsg_Click(object sender, EventArgs e)
        {
            try
            {
                //设置发送目标客户端
                string ipport = cbx_IPEndPoint.Text;//从下拉框中获取选中的目标IPPORT
                if (ipport == "")
                { MessageBox.Show("请选择一个客户端!"); return; }
                //将要发送的数据转换为byte数组
                byte[] buffer = Encoding.Default.GetBytes(txt_Send.Text);

                //发送数据
                dic[ipport].Send(buffer);

                //将要发送的数据显示到Server窗体中
                txt_SrvMsg.AppendText(txt_Send.Text + "\r\n");
            }
            catch (Exception ex)
            {
                txt_SrvMsg.AppendText(ex.Message + "\r\n");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ASimpleSocketClient
{
    public partial class frm_Client : Form
    {
        public frm_Client()
        {
            InitializeComponent();
        }

        //窗体加载事件
        private void frm_Client_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //连接 按钮单击事件
        private void btn_Connect_Click(object sender, EventArgs e)
        {
            //需要连接的目标IP(服务器端的IP)
            IPAddress ip = IPAddress.Parse(txt_IP.Text);

            //目标端口(服务器端的侦听端口)
            int port = int.Parse(txt_Port.Text);

            //构建IP终结点
            IPEndPoint ippoint = new IPEndPoint(ip, port);

            try
            {
                //连接到服务器
                client.Connect(ippoint);
                txt_ClientMsg.AppendText("连接成功!" + "\r\n");
                txt_ClientMsg.AppendText("服务器:" + client.RemoteEndPoint.ToString() + "\r\n");
                txt_ClientMsg.AppendText("客户端:" + client.LocalEndPoint.ToString() + "\r\n");

                //连接成功后就可以接收服务器端发送的消息了
                Thread th = new Thread(ReceiveMsg);
                th.IsBackground = true;
                th.Start();
            }
            catch (Exception ex)
            {
                txt_ClientMsg.AppendText(ex.Message + "\r\n");
            }
        }

        //接收服务器端发送的消息
        void ReceiveMsg()
        {
            while (true)
            {
                try
                {
                     * ];
                    int n = client.Receive(buffer);
                    , n);
                    txt_ClientMsg.AppendText(client.RemoteEndPoint.ToString() + ":" + s + "\r\n");
                }
                catch (Exception ex)
                {
                    txt_ClientMsg.AppendText(ex.Message + "\r\n");
                    break;
                }
            }
        }

        //发送消息 按钮单击事件
        private void btn_SendMsg_Click(object sender, EventArgs e)
        {
            //客户端给服务器端发送消息
            if (client != null)
            {
                try
                {
                    byte[] buffer = Encoding.Default.GetBytes(txt_Send.Text);
                    client.Send(buffer);
                    txt_ClientMsg.AppendText(txt_Send.Text + "\r\n");
                }
                catch (Exception ex)
                {
                    txt_ClientMsg.AppendText(ex.Message + "\r\n");
                }
            }
        }
    }
}

socket编程详解,转自http://www.sme-cn.com:82/archives/669的更多相关文章

  1. Linux的SOCKET编程详解(转)

    Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...

  2. 【ARM-Linux开发】Linux的SOCKET编程详解

    Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...

  3. linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解

    最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...

  4. Linux的SOCKET编程详解

    1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 U ...

  5. [转]Linux的SOCKET编程详解

    From : http://blog.csdn.net/hguisu/article/details/7445768 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在 ...

  6. PHP Socket 编程详解

    PHP中的实现 服务端 <?php set_time_limit(0); // 设置主机和端口 $host = "127.0.0.1"; $port = 12387; // ...

  7. socket编程详解

    http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html http://blog.csdn.net/hguisu/article/de ...

  8. socket原理详解

    1.什么是socket 我们知道进程通信的方法有管道.命名管道.信号.消息队列.共享内存.信号量,这些方法都要求通信的两个进程位于同一个主机.但是如果通信双方不在同一个主机又该如何进行通信呢?在计算机 ...

  9. windows socket函数详解

    windows socket函数详解 近期一直用第三方库写网络编程,反倒是遗忘了网络编程最底层的知识.因而产生了整理Winsock函数库的想法.以下知识点均来源于MSDN,本人只做翻译工作.虽然很多前 ...

随机推荐

  1. <Linux> Xen虚拟机下挂载

    //创建源vdisk挂载目录: mkdir vd1 //创建目标vdisk挂载目录: mkdir vd2 //只需第一次执行:  iscsiadm -m discovery --type sendta ...

  2. 【codeforces 758A】Holiday Of Equality

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  3. JFinal redis cluster集群插件

    JFinal redis cluster集群插件 JFinal 框架到了2.1版本号,可是依旧仅仅支持redis的主从集群,没有看到Cluster集群的插件.笔者照着主从的插件方式,改了改,实现了个简 ...

  4. 【codeforces 602E】Kleofáš and the n-thlon

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  5. 有奖试读&amp;征文--当青春遇上互联网,是否能点燃你的创业梦

    时至今日,互联网已经切入我们每一个人的工作.生活和学习的每一个角落.利用互联网这个工具,有人游戏,有人购物,有人上课,有人交友,而有那么一部分人去利用它完毕人生最完美的逆袭.相信每一个人心中都有个创业 ...

  6. C#写COM组件,JS调用控件

    1.c#2005中新建项目,类型为类库,项目名为AddCom确定. 配置:右键点击解决方案资源管理器中的AddCom,选择“属性”,选择“生成”,选择“为COM Interop注册(_P)” 2.打开 ...

  7. CodeBlocks环境搭建及创建第一个C++程序

    某业界大牛推荐最佳的途径是从raytracing入门,所以本屌开始学习<Ray Tracing In One Weekend>. 该书是基于C++的.本屌从未学过C++.感觉告诉我,要先搭 ...

  8. 打开一个很好的介绍Lucene4 FST文章

    我没有看到源代码.看到这个博客了解一些基本的,像笔者下: http://download.csdn.net/download/guanxinquan/7380591 http://blog.sina. ...

  9. WPF--动态添加控件、访问控件

    //WPF窗口采用默认的Grid布局控件,其“Name”值为“grid1”,在“grid1”中添加三个Button按钮.动态添加控件并访问这些控件的代码如下: private void button1 ...

  10. javascript相框echarts插件实现酷立方效果图的人

    最近由于项目需求,我们需要做的一类似网络效应的人立方效果,很多文件中的查询之后.百度发现echarts开源组件非常适合,而加载速度是伟大的.echarts图形主要使用html5这些新功能做,使用can ...