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. iOS开发网络篇—大文件的多线程断点下载

    http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...

  2. (转载)XML解析之-XStream解析

    转载来源:http://hwy584624785.iteye.com/blog/1168680 本例使用XStream生成一个xml文件,再发序列化xml文件内容. XStream是一个简单的类库,可 ...

  3. linux kernel input 子系统分析

    Linux 内核为了处理各种不同类型的的输入设备 , 比如说鼠标 , 键盘 , 操纵杆 , 触摸屏 , 设计并实现了一个对上层应用统一的试图的抽象层 , 即是Linux 输入子系统 . 输入子系统的层 ...

  4. 读书笔记-JVM

    局部变量表(虚拟机栈中的一部分)在编译期完成分配,运行期不会再改变大小: 每个方法对应一个栈帧(存储局部变量表.操作数栈.动态链接.方法出口等),栈帧被存储到虚拟机栈中,每个线程对应一个虚拟机栈,方法 ...

  5. 5-python学习——条件语句

    5-python学习——条件语句 5-python学习——条件语句 条件语句if else形式 if else条件语句说明 测试一下 编程语言一般都由这么几个部分组成 变量 条件分支语句 循环语句 函 ...

  6. net-snmp-5.7.3配置编译安装

    net-snmp-5.7.3配置编译安装 [TOC] 先看一下系统环境 o@o-pc:~/work/_snmp/net-snmp-5.7.3$ uname -a Linux o-pc 3.16.0-3 ...

  7. oracle数据库备份

    --数据库备份--导出 exp userid=shoppingsys/shoppingsys@orcl file=/home/oracle/shoppingsys.dmp log=/home/orac ...

  8. spring boot redis缓存JedisPool使用

    spring boot redis缓存JedisPool使用 添加依赖pom.xml中添加如下依赖 <!-- Spring Boot Redis --> <dependency> ...

  9. 使用jsvc启动tomcat

    1.在/usr/local/apache-tomcat-7.0.68/bin中有commons-daemon-native.tar.gz  压缩包 2.解压commons-daemon-native. ...

  10. effective OC2.0 52阅读笔记(五 内存管理)

    第五章:内存管理 29 理解引用计数 30 以ARC简化引用计数 总结:ARC通过命名约定将内存管理规则标准化.其他编程语言很少像OC这样强调命名.ARC通过设置全局数据结构(此数据结构的具体内容因处 ...