9.1 Socket相关概念

IP地址

每台联网的电脑都有一个唯一的IP地址。

长度32位,分为四段,每段8位,用十进制数字表示,每段范围 0 ~ 255

特殊IP:127.0.0.1 用户本地网卡测试

版本:V4(32位) 和 V6(128位,分为8段,每段16位)

端口

在网络上有很多电脑,这些电脑一般运行了多个网络程序。每种网络程序都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的网络程序。

常用端口:21 FTP ,25 SMTP ,110 POP3 ,80 HTTP , 443 HTTPS

有两种常用Socket类型:

流式Socket(STREAM):
是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低

数据报式Socket(DATAGRAM):
是一种无连接的Socket,对应于无连接的UDP服务应用.不安全(丢失,顺序混乱,在接收端要分析重排及要求重发),但效率高.

9.1.1 Socket 流式(服务器端和客户端)

服务器端的Socket(至少需要两个)

一个负责接收客户端连接请求(但不负责与客户端通信)

每成功接收到一个客户端的连接便在服务端产生一个对应的负责通信的Socket

在接收到客户端连接时创建.

为每个连接成功的客户端请求在服务端都创建一个对应的Socket(负责和客户端通信).

客户端的Socket

客户端Socket

必须指定要连接的服务端IP地址和端口。

通过创建一个Socket对象来初始化一个到服务器端的TCP连接

9.1.2 Socket的通讯过程

服务器端

•申请一个socket

//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

•绑定到一个IP地址和一个端口上

//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text));
//2.2 绑定端口(其实内部就像系统端口表中注册了一个端口,并指定了当前句柄)
socketWatch.Bind(endPoint);
//2.3 设置监听队列
socketWatch.Listen(10);

•开启侦听,等待接授连接

//2.4.开始监听 此方法会阻断当前线程。知道有其他程序连接,才能执行完毕
Socket socket = socketWatch.Accept(); //【通信套接字】注意这里,Accept返回类型Socket

客户端

•申请一个socket

•连接服务器(指明IP地址和端口号)

//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口
//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text));
//3.向服务端发送连接请求
socketWatch.Connect(endPoint);

服务器端接到连接请求后,产生一个新的socket(端口大于1024)与客户端建立连接并进行通讯,原监听socket继续监听。

 

 

9.2 使用线程调用监听套接字

 

监听demo
监听demo

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 _02Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;//检查非法跨线程调用
} //服务端 监听套接字
Socket socketWatch = null;
//服务端 监听线程
Thread thread = null; /// <summary>
/// 监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Listen_Click(object sender, EventArgs e)
{
//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口
//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text));
//2.2 绑定端口(其实内部就像系统端口表中注册了一个端口,并指定了当前句柄)
socketWatch.Bind(endPoint);
//2.3 设置监听队列
socketWatch.Listen(10);
thread = new Thread(WathchConnection);
thread.IsBackground = true;
thread.Start();
ShowMsg("服务器启动。。");
} void WathchConnection()
{
//2.4.开始监听 此方法会阻断当前线程。知道有其他程序连接,才能执行完毕
socketWatch.Accept();
ShowMsg("有客户端连接~!");
} //显示监听消息方法
void ShowMsg(string strmsg)
{
this.txt_Show.AppendText(strmsg + "\r\n");
}
}
}

 

9.3 客户端连接服务端

向服务端发送连接请求demo
向服务端发送连接请求demo

//客户端 监听套接字
Socket socketWatch = null; private void btn_Connction_Click(object sender, EventArgs e)
{
//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口
//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text));
//3.向服务端发送连接请求
socketWatch.Connect(endPoint);
}

 

9.4 客户端向服务端发送消息

不足:点了一次发送后,再点就没反映了。

服务端

3.通信套接字 监听 客户端 消息
3.通信套接字 监听 客户端 消息

void WathchConnection()
{
//2.4.开始监听 此方法会阻断当前线程。知道有其他程序连接,才能执行完毕
Socket socket = socketWatch.Accept(); //【通信套接字】注意这里,Accept返回类型Socket
ShowMsg("有客户端连接~!"
); //------------------3.通信套接字 监听 客户端 消息------------------------
//3.1 创建缓存区
byte[] arrMsg = new byte[1024 * 1024 * 1];
//3.2 接收客户端的消息,并存如缓存区。注意:Receive会阻断当前的线程
socket.Receive(arrMsg);
//3.3 将接收的消息转化为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg);
//3.4 将消息 显示到 txt_show
ShowMsg(strMsg);
} //显示监听消息方法
void ShowMsg(string strmsg)
{
this.txt_Show.AppendText(strmsg + "\r\n"
);
}

客户端

发送消息
发送消息

/// <summary>
/// 发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Send_Click(object sender, EventArgs e)
{
string strMsg = this.txt_Input.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
socketWatch.Send(arrMsg);
}

 

 

9.5 服务端循环接收消息

解决:9.4的只能发送1次的问题

创建一个线程,还是在WathchConnection里修改

服务端循环接收消息demo
服务端循环接收消息demo

void WathchConnection()
{
//2.4.开始监听 此方法会阻断当前线程。知道有其他程序连接,才能执行完毕
Socket socket = socketWatch.Accept(); //【通信套接字】注意这里,Accept返回类型Socket
ShowMsg("有客户端连接~!"
); Thread thread2 = new Thread(ReceiveMsg);
thread2.IsBackground = true;
//有参数的线程(参数只能是object)
thread2.Start(socket);
} bool isReceive = true;
void ReceiveMsg(object o)
{
Socket socket2 = o as Socket;
//------------------3.通信套接字 监听 客户端 消息------------------------
//3.1 创建缓存区
byte[] arrMsg = new byte[1024 * 1024 * 1];
while (isReceive)
{
//3.2 接收客户端的消息,并存如缓存区。注意:Receive会阻断当前的线程
socket2.Receive(arrMsg
);
//3.3 将接收的消息转化为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg
);
//3.4 将消息 显示到 txt_show
ShowMsg(strMsg
);
}

 

9.6 服务端向客户端发送消息

服务端

服务端向客户端发送消息:Server
服务端向客户端发送消息:Server

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;//线程Z namespace _02Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;//检查非法跨线程调用
} //服务端 监听套接字
Socket socketWatch =
null;
//服务端 监听线程
Thread thread = null;
//字典集合(【与客户端通信的套接字】的标识保存起来)
Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
/// <summary>
/// 监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Listen_Click(object sender, EventArgs e)
{
//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp
);
//绑定端口
//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text
);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text
));
//2.2 绑定端口(其实内部就像系统端口表中注册了一个端口,并指定了当前句柄)
socketWatch.Bind(endPoint
);
//2.3 设置监听队列
socketWatch.Listen
(10);
thread = new Thread(WathchConnection
);
thread.IsBackground = true
;
thread.Start
();
ShowMsg("服务器启动。。"
);
}
void WathchConnection()
{
//2.4.开始监听 此方法会阻断当前线程。知道有其他程序连接,才能执行完毕
Socket socket = socketWatch.Accept();
//【通信套接字】注意这里,Accept返回类型Socket //------------------------4.start-------------------------
//4.1将当前连接成功的【与客户端通信的套接字】的标识保存起来,并显示在列表中
//将远程客户端的 IP和端口 字符串 存入列表
lb_OnLine.Items.Add(socket.RemoteEndPoint.ToString());
//4.2 将服务器端的通信套接字 存入 字典集合
dict.Add(socket.RemoteEndPoint.ToString(), socket);
//-----------------------4.end--------------------------- ShowMsg("有客户端连接~!");
Thread thread2 = new Thread(ReceiveMsg
);
thread2.IsBackground = true
;
//有参数的线程(参数只能是object)
thread2.Start(socket
);
} /// <summary>
/// 4.3服务端向客户端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ServerSend_Click(object sender, EventArgs e)
{
string strClient = lb_OnLine.Text;
if (dict.ContainsKey(strClient))
{
string strMsg = txt_ServerInput.Text.Trim();
ShowMsg("向客户端【" + strClient + "】说:" + strMsg);
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
dict[strClient].Send(arrMsg);
}
}
bool isReceive = true;
void ReceiveMsg(object o)
{
Socket socket2 = o as Socket;
//------------------3.通信套接字 监听 客户端 消息------------------------
//3.1 创建缓存区
byte[] arrMsg = new byte[1024 * 1024 * 1];
while (isReceive)
{
//3.2 接收客户端的消息,并存如缓存区。注意:Receive会阻断当前的线程
socket2.Receive(arrMsg);
//3.3 将接收的消息转化为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg).Trim();
//3.4 将消息 显示到 txt_show
ShowMsg(strMsg);
} } //显示监听消息方法
void ShowMsg(string strmsg)
{
this.txt_Show.AppendText(strmsg + "\r\n"
);
}

}
}

户端

服务端向客户端发送消息:Client
服务端向客户端发送消息:Client

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 _02客户端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
//客户端 通信套接字
Socket socketWatch = null;
//客户端 通信线程
Thread threadMsg = null; /// <summary>
/// 连接服务器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Connction_Click(object sender, EventArgs e)
{
//1.创建监听套接字 使用 ip4协议,流式传输,TCP连接
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.
Tcp);
//绑定端口
//2.1 获取网络节点对象
IPAddress address = IPAddress.Parse(this.txt_IP.Text
);
IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txt_Port.Text
));
//3.向服务端发送连接请求
socketWatch.Connect(endPoint
);
ShowMsg("连接服务器成功!.."); //4.4.开启通信线程
threadMsg = new Thread(ReceiveMsg);
threadMsg.IsBackground = true;
threadMsg.Start();
} bool isRec = true;
void ReceiveMsg()
{
byte[] arrMsg = new byte[1024 * 1024 * 1];
while (isRec)
{
socketWatch.Receive(arrMsg);
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg);
ShowMsg("服务端说:" + strMsg);
}
} /// <summary>
/// 发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Send_Click(object sender, EventArgs e)
{
string strMsg = this.txt_Input.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
socketWatch.Send(arrMsg);
} void ShowMsg(string strmsg)
{
this.txt_Show.AppendText(strmsg + "\r\n");
}
}
}

 

问题:

1.不换行

获取真实长度

//3.2 接收客户端的消息,并存如缓存区。注意:Receive会阻断当前的线程
int realLength = socket2.Receive(arrMsg);
//3.3 将接收的消息转化为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg,0,realLength);

Asp.Net - 9.socket(聊天室)的更多相关文章

  1. Java Socket聊天室编程(二)之利用socket实现单聊聊天室

    这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...

  2. Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

    这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...

  3. python socket 聊天室

    socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...

  4. TCP/IP以及Socket聊天室带类库源码分享

    TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...

  5. 015. asp.net实现简易聊天室

    通过Application和Session来实现简单的聊天室和在线用户数统计 Global.asax代码: <%@ Application Language="C#" %&g ...

  6. html5 WebSocket 与 PHP socket 聊天室原理

    html js <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  7. 基于Spring 4.0 的 Web Socket 聊天室/游戏服务端简单架构

    在现在很多业务场景(比如聊天室),又或者是手机端的一些online游戏,都需要做到实时通信,那怎么来进行双向通信呢,总不见得用曾经很破旧的ajax每隔10秒或者每隔20秒来请求吧,我的天呐(),这尼玛 ...

  8. Python socket聊天室程序

    http://blog.csdn.net/calling_wisdom/article/details/42524745 今天用python的socket模块实现了一个聊天室的程序 虽然功能比较简单, ...

  9. 【Unity3D自学记录】Unity3D网络之Socket聊天室初探

    首先创建一个服务端程序,这个程序就用VS的控制台程序做即可了. 代码例如以下: using System; using System.Collections.Generic; using System ...

随机推荐

  1. python os.path.dirname 是什么目录

    这个获取文件路径中所在的目录. 1 2 3 4 5 6 7 In [1]: import os   In [2]: os.__file__ Out[2]: '/usr/lib/python2.7/os ...

  2. PYTHON 购物车程序

    product_list = [ ('iphone',50000), ('Mac Pro',9900), ('Bike',8000), ('Watch',160000), ('Coffee',600) ...

  3. HDU——PKU题目分类

    HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...

  4. 深入mysql "on duplicate key update" 语法的分析

    如果在INSERT语句末尾指定了on duplicate key update,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则在出现重复值的行执行UPDATE:如果不 ...

  5. faad解码aac

    // faad2.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include <cassert> #include <io ...

  6. phpcms分页用法简介

    PHPCMS分页的用法 前面需要有引用的list,代码如下: {pc:content action="lists" catid="11" order=" ...

  7. Java对象访问 类的静态变量

    Java类的静态变量用对象和类名都能访问,一般用类名,但如果用对象来访问静态变量呢,有何种效果? 测试一下: package JavaTest; public class test{ public s ...

  8. java前后台之间传值的几种方式

    自己写的代码太少,有时候前后台传值还写的不是很熟练,现在总结一下,加深下印象. 1.jquery的Ajax传值 ---->前台到后台 期望功能:把前台用户输入的信息保存在数据库里. 前台jsp代 ...

  9. jQuery数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解

    1. $.each(array, [callback]) 遍历[常用] 解释: 不同于例遍jQuery对象的$().each()方法,此方法可用于例遍任何对象.回调函数拥有两个参数:第一个为对象的成员 ...

  10. C#之系统自带保存属性

    源代码下载链接 程序开发很多时候需要根据运行环境做不通的参数配置,通过写ini之类的文本文件是一种方法,但这种方法也同时会把数据暴露 Winform开发中可以将需要配置的字段属性保存到程序中(其实也是 ...