一  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. 《Kinect应用开发实战》读书笔记---干货集合

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接: http://blog.csdn.net/cartzhang/article/details/45029841 作者:ca ...

  2. IT忍者神龟之Hibernat持久化对象-数据表映射配置回想

    1.持久化对象POJO编写规则: 1) 有空參public构造器: 2) 提供标识属性.映射数据表主键: 3) 属性提供setter和getter方法. 4) 属性使用基本数据类型的包装类型.基本类型 ...

  3. 基于 Android NDK 的学习之旅-----HelloWorld

    Hello World作为所有编程语言的起始阶段,占据着无法改变的地位,所有中/英/法/德/美……版本的编程教材中,hello world总是作为第一个TEST记录于书本之中,所有的编程第一步就在于此 ...

  4. JM-1 手机网站开发测试环境搭建

    JM-1 手机网站开发测试环境搭建 一.总结 一句话总结:WEB服务器环境可实现局域网内轻松访问.360wifi可以实现局域网. 二.微网站开发环境: 1.把微网站放到本机wamp环境下,用pc浏览器 ...

  5. NOIP模拟 回文序列 - DP

    题意: 如果一个字符串等于s和t的长度之和(\(l \le 50\)),并且可以拆成两个字符串子序列,分别与s和t相同,那么它就是s和t的一个并字符串(从字符串中选出若干个可以不连续的字符按照原序列写 ...

  6. poj 2594 Treasure Exploration 二分图匹配

    点击打开链接题目链接 Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7215   ...

  7. NotifyICon使用

    2010-04-11 15:47 by Ju2ender, 1438 visits, 网摘, 收藏, 编辑 最常见使用NotifyIcon的程序就是QQ了,当初我非常好奇这通知区域的小企鹅是怎样随着Q ...

  8. 二叉苹果树 - 二叉树树型DP

    传送门 中文题面: 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点,这棵树共有N 个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一 ...

  9. [GeekBand] 设计模式——工厂模式学习笔记

     本文参考文献:GeekBand课堂内容,授课老师:李建忠 :大话设计模式 其余的模式方法请自行查看Geekband相关课程,在此不累述. 这周的课题是: 针对DrawingSystem中的基类Sha ...

  10. 新一代Xamarin

    新一代Xamarin竟然可以将.NET代码原生编译成:Jar包供Java原生调用.swift类库.obj-c类库.C++类库 供目标平台传统代码直接调用 之前和很多朋友聊到Xamarin觉得确实不错, ...