黑马程序员 .NET学习笔记 <8>

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

一、IP和端口

1、  IP在网络上为每一台计算机的地址,端口是网络中每台计算机的不同程序访问的入口。

2、  计算机给每个程序绑定一个端口,用于网络访问。

二、套接字

1、应用程序通过系统和网络设备进行交互,微软把这些程序封装成一个socket类,它是程序与外界联系的一个通道,用于描述IP地址和端口,计算机的每个服务都打开一个socket,并绑定到一个端口。

2、就像电话通信方式一样,在通信之前先申请一个socket对象,同时必须知道对方的IP地址和端口号,相当于对方有一个固定的socket,然后向对方发送呼叫,相当于发送连接请求,当一方关闭socket,就相当于关闭两者之间的通信。

3、例:http使用80端口,ftp使用21端口,smtp使用23端口。

4、socket信息的传递方式有两种:

1)基于流的传输(stream):类似于电话,特点是即时性,一方发送,另一方随时接受;

2)基于报文的传输(datagram):类似于写信,特点是不论对方是否准备好,都可以先发送,但也有可能丢失。

5、socket一般应用模式:

         1)必须有一个服务端和客户端;

         2)先生成一个服务端的套接字用于监听,然后客户端的套接字与服务端“接待套接字”连接;

         3)服务端“接待套接字”收到客户端的请求后,启动另外一个“通信套接字”与客户端通信。

6、服务端套接字至少有两个:一个负责接收客户端请求,但不负责通信,在成功接收到客户端请求后,为该客户端创建一个对应的套接字。

7、客户端有一个套接字:必须指定要连接的服务器地址和端口,创建一个socket对象来初始化一个到服务器的TCP连接。

8、通信基本流程图:

         1)服务器:创建套接字socket()->绑定监听端口bind()->设置监听队列listen()->循环等待客户连接accept()(如果建立通信,则创建另外一个套接字)->接收数据receive()/发送数据send()/捕获异常->断开通信close();

         2)客户端:创建套接字socket()->连接建立connect()->接收数据receive()/发送数据send()>断开通信close()。

9、聊天通信程序:

1)服务器:

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.Sockets;
using System.Net;//IPAddress IPEndPoint IP和端口类
using System.Threading;

namespace CommunicationProgram
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        
        Thread threadwatch = null;  //创建一个用于accept的线程
        Socket SocketWatch = null;  //负责监听的套接字
        //Socket connection = null;   //负责通信的套接字

        Dictionary<string, Socket> dict = new Dictionary<string, Socket>(); //泛型字典集合

        private void btnListen_Click(object sender, EventArgs e)
        {
            try
            {
                SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建套接字:IPv4,流传输,TCP协议
                IPAddress address = IPAddress.Parse(txtip.Text.Trim());   //获得IP地址:将IP地址自动转换赋给地址对象
                IPEndPoint EndPoint = new IPEndPoint(address, Convert.ToInt32(txtfort.Text));  //创建包含IP和端口的网络节点对象
                SocketWatch.Bind(EndPoint); //将负责监听的socket绑定到唯一的节点
                SocketWatch.Listen(10); //设置监听队列最大数量为10,超过了就抛出异常
                //Socket connection = SocketWatch.Accept();   //创建新的套接字与客户端通信,accept()如果没有接受,则一直在循环等待,可以放在另一个线程中处理
                threadwatch = new Thread(watchconnecting);  //创建监听线程,并传入监听方法
                threadwatch.IsBackground = true;    //设置为后台线程
                threadwatch.Start();    //开启线程
                ShowMessage("服务器启动!");
            }
            catch(Exception a)
            {
                MessageBox.Show("error");
            }
        }

        void watchconnecting()
        {
            while (true)    //持续不断地监听客户端的连接请求
            {
                Socket connection = SocketWatch.Accept();//创建新的套接字与客户端通信,accept()如果没有接受,则一直在循环等待
                lbonline.Items.Add(connection.RemoteEndPoint.ToString());   //向列表中添加客户端节点信息,作为唯一标识
                dict.Add(connection.RemoteEndPoint.ToString(),connection);  //在字典集合中加入此时接入服务器的客户端节点
                ShowMessage("客户端连接成功!"+connection.RemoteEndPoint.ToString());   //获取客户端远程IP和端口
            }
        }

        void ShowMessage(string msg)
        {
            txtmessage.AppendText(msg + "\r\n");
        }

        private void btnsend_Click(object sender, EventArgs e)
        {
            try
            {
                string SendMsg = txtsend.Text.Trim();
                byte[] arr = System.Text.Encoding.UTF8.GetBytes(SendMsg);//将字符串转换为utf8字节数组
                string strclient = lbonline.Text;   //获得列表中选中的客户端远程节点
                dict[strclient].Send(arr);  //通过节点找到字典集合中对应的客户端套接字,并调用send方法发送数据
                //connection.Send(arr);//发送数据
                ShowMessage("发送数据" + SendMsg);
            }
            catch (Exception j)
            {
                MessageBox.Show("error");
            }
        }
        /// <summary>
        /// 群发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnall_Click(object sender, EventArgs e)
        {
            string SendMsg = txtsend.Text.Trim();
            byte[] arr = System.Text.Encoding.UTF8.GetBytes(SendMsg);//将字符串转换为utf8字节数组
            for (int i = 0; i < lbonline.Items.Count; i++)
            {
                dict[lbonline.Items[i].ToString()].Send(arr);
            }
        }
    }
}

2)客户端:

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.Sockets;
using System.Net;
using System.Threading;

namespace ClientApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        Thread receive = null;
        Socket client = null;
        byte[] remsg = null;
        string remsgg = null;

        



        private void btnconnect_Click(object sender, EventArgs e)
        {
            try
            {
                IPAddress address = IPAddress.Parse(txtip.Text.Trim());
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtfort.Text.Trim()));
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(endpoint);
                receive = new Thread(receivemsg);
                receive.IsBackground = true;
                receive.Start();
            }
            catch (Exception t)
            {
                MessageBox.Show("error");
            }
            //ShowMessage("");
        }

        void receivemsg()
        {
            while (true)
            {
                remsg = new byte[1024 * 1024 * 2];
                int length = client.Receive(remsg);  //接收服务器传来的数据,并返回真正接收到的数据长度
                remsgg = System.Text.Encoding.UTF8.GetString(remsg,0,length);
                ShowMessage(remsgg);
            }
        }

        void ShowMessage(string msg)
        {
            txtmessage.AppendText(msg + "\r\n");
        }
    }
}


3)服务端循环监听:在监听方法中加入while(true)循环。

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值