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. linux中diff命令用法

    diff 命 令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版 本的diff还支持二进制文件.diff程 ...

  2. git 教程(8)--删除文件

    在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:

  3. echarts之字符云tooltip显示混乱问题的解决办法

    echarts字符云中tooltip显示混乱主要表现为一下两点: 1.字体与其显示框内容不对应鼠标识别错误 解决思路: 就是option里的数据要对value降序排序(这一点很关键,是必须的一步) 把 ...

  4. 【GoLang】GoLang 错误处理 -- 官方推荐方式 示例

    最严谨的方式,Always检查error,并做相应的处理 项目结构: 代码: common.go: package common import ( "github.com/pkg/error ...

  5. CEF3开发者系列之CEF3入门

    CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chromium项目主要是为Google Chrome应用开发的, ...

  6. FastReport 使用说明

    FastReport TfrxReport 此为最主要的报表元件,一个 TfrxReport 元件组成一份报表.在设计时期,双击此 元件可打开报表设计器(Report Designer),此元件拥有所 ...

  7. net use与shutdown配合使用,本机重启远程服务器

    net use与shutdown配合使用,本机重启远程服务器   今天服务器出现问题了,能ping通,但就是远程登录服务器后,服务器无法响应.   在本机测试发现ftp服务可以使用,于是就想通过ftp ...

  8. 4.nodejs权威指南--TCP和UDP

    1. TCP和UDP 1.1 TCP服务端 var net = require('net'); var server = net.createServer(); server.on('connecti ...

  9. DataStage

    parallel job shell调用:dsjob ./dsjob -run -mode NORMAL -paramfile xxx.param <PROJECT> <JOB> ...

  10. Match:Power Strings(POJ 2406)

     字符串前缀的阶 题目大意:求前缀的阶 和POJ1961是一样的,KMP的Next数组的应用,不要用STL,不要一个一个读入字符(IO永远是最慢的) #include <iostream> ...