黑马程序员-多线程聊天室
来源:互联网 发布:天天模拟器mac版 编辑:程序博客网 时间:2024/05/16 16:56
---------------------- Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------
服务端界面
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.IO;
namespace myserver
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;//打开微软对TextBox的 跨线程 操作
}
Socket socketWatch = null;//创建一个套接字
Thread threadWatch = null;//创建一个监听线程
//创建一个监听多个客户端的 套接字 字典
Dictionary<string, Thread> dictthread = new Dictionary<string, Thread>();
private void btsart_Click(object sender, EventArgs e)
{
//创建一个负责监听的套接字 参数(使用IPV4寻址方式 , 使用流式连接 , 使用TCP协议传输数据)
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//取得一个IPAddress的类型的ip地址
IPAddress ip = IPAddress.Parse(txtip.Text.Trim());
//取得ip地址和端口
IPEndPoint point = new IPEndPoint(ip, int.Parse(txtport.Text.Trim()));
//连接要监听套接字绑定到唯一的IP和端口.
socketWatch.Bind(point);
//设置队列长度
socketWatch.Listen(10);
//开始监听 客户端的 连接 请求
//Socket xin = socketWatch.Accept();//Accept会阴断当前线程
Mymsc("监听成功");
//创建一个线程 监听客户端新的请求
threadWatch = new Thread(Connting);
//设为后台线程
threadWatch.IsBackground = true;
//开始线程
threadWatch.Start();
//防止第二次服务连接
btsart.Text="服务启动";
btsart.Enabled = false;
}
/// <summary>
/// 监听客户端的请求,存入字典,做为向哪个客户端进行通信的标识.
/// </summary>
Dictionary<string,Socket> dict=new Dictionary<string,Socket>();
void Connting()
{
while (true)//不断的 监听 新的连接 请求
{
//开始监听 客户端的 连接 请求 Accept会阴断当前线程
Socket xin = socketWatch.Accept();//一旦监听到请求,就会创建一个 xin 套接字 来进行通信
//向列表控中 添加 套接字客户端 的ip 和 端口,作为客户端的标识
listBox1.Items.Add(xin.RemoteEndPoint.ToString());
//将与客户端通信的 套接字对象 xin 添加到 键盘值和集合中,并以客户端ip端口为主键
dict.Add(xin.RemoteEndPoint.ToString(), xin);
//创建线程委托
ParameterizedThreadStart slp=new ParameterizedThreadStart(Msgwatch);
//为新创建的套接字 建立一个线程 执行监听来自客户端的数据
Thread jsMsg = new Thread(slp);
//设置为后台线程
jsMsg.IsBackground = true;
//开始运行线程 并传入新建立的套接字win的参数
jsMsg.Start(xin);
//把线程加入到dictthread的字典
dictthread.Add(xin.RemoteEndPoint.ToString(), jsMsg);
Mymsc("客户端连接成功" + xin.RemoteEndPoint.ToString());
//msgWatch = new Thread(Msgwatch);
//msgWatch.IsBackground = true;
//msgWatch.Start();
}
}
/// <summary>
/// 监听来自客户端传来的数据
/// </summary>
/// <param name="socket"></param>
void Msgwatch(object socket)
{
//不停的监听
while (true)
{
//把获取的参数转换为Socket类型
Socket socketWatch = socket as Socket;
//定个一个1M的字节数组 用来接收来自客户端的数据
byte[] jieshou = new byte[1024 * 1024 * 2];
int length = 1;
try
{
//得到传过来字节的长度 jieshou得到传来的数据
length = socketWatch.Receive(jieshou);
}
catch (SocketException )//判断是否有Socket的异常发生
{
//删除字典内关闭了的用户
dict.Remove(socketWatch.RemoteEndPoint.ToString());
//删除了线程
dictthread.Remove(socketWatch.RemoteEndPoint.ToString());
//删除被关闭的用户
listBox1.Items.Remove(socketWatch.RemoteEndPoint.ToString());
Mymsc(socketWatch.RemoteEndPoint.ToString() + "断开了连接");
break;
}
if (jieshou[0] == 0)
{
//把传来的字节数据转换为字符串
string str = System.Text.Encoding.UTF8.GetString(jieshou, 1, length - 1);
//显示得到的数据
Mymsc("接收到" + socketWatch.RemoteEndPoint.ToString() + "数据:" + str);
}
else if (jieshou[0] == 1)
{
SaveFileDialog savefile = new SaveFileDialog();
if (savefile.ShowDialog() == DialogResult.OK)
{
using (FileStream fs = new FileStream(savefile.FileName, FileMode.CreateNew))
{
fs.Write(jieshou, 1, length - 1);
}
}
Mymsc("保存成功" + savefile.FileName);
}
}
}
/// <summary>
/// 向文本框中输出数据
/// </summary>
/// <param name="msc"></param>
void Mymsc(string msc)
{
textBox1.AppendText(msc + "\r\n");
}
private void 发送数据_Click(object sender, EventArgs e)
{
//得到要发送的数据
string str = txtmsg.Text.Trim();
//把需要发送的数据转换成UTF8的字节
byte[] byt=System.Text.Encoding.UTF8.GetBytes(str);
if (string.IsNullOrEmpty(listBox1.Text))
{
MessageBox.Show("请选择要发送的好友");
}
else
{
//获取选中的客户端ip和端口
string stryh = listBox1.Text;
//向xin套接字发送数据
dict[stryh].Send(byt);
//显示发出的数据
Mymsc("发出去的数据" + str);
}
//表空txtmsg文本内的数据
txtmsg.Clear();
//获得焦点
txtmsg.Focus();
}
private void button1_Click(object sender, EventArgs e)
{
//得到要发送的数据
string str = txtmsg.Text.Trim();
//把需要发送的数据转换成UTF8的字节
byte[] byt = System.Text.Encoding.UTF8.GetBytes(str);
foreach (Socket d in dict.Values)
{
d.Send(byt);
}
}
}
}
客户端界面
代码如下:
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;
using System.IO;
namespace 客户端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Thread jieshou = null;
Socket scoketkehu = null;
private void btlish_Click(object sender, EventArgs e)
{
//创建一个套接字 参数(指定ipv4寻址方式,使用流式连接,使用TCP数据传输)
scoketkehu = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获取ip地址
IPAddress address = IPAddress.Parse(txtip.Text.Trim());
//指定要连接的ip和端口
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtport.Text.Trim()));
//连接服务端
scoketkehu.Connect(endpoint);
Mymsc("连接成功");
//建立一个线程,监听服务端传来的消息
jieshou = new Thread(js);
//把线程设置为后台线程
jieshou.IsBackground = true;
//线程开始
jieshou.Start();
}
/// <summary>
/// 不停监听服务端传来的消息
/// </summary>
void js()
{
while (true)
{
//建立一个1M的byte字节的数组
byte[] arrMsg = new byte[1024 * 1024];
//接收传过来的信息存到arrMsg字节数组中,并把长度赋给i
int i=scoketkehu.Receive(arrMsg);
//把字节数组转换成字符串
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg,0,i);
//输出到文本框
Mymsc("服务端信息:"+strMsg);
}
}
/// <summary>
/// 向文本框中输出信息
/// </summary>
/// <param name="msc"></param>
void Mymsc(string msc)
{
textBox1.AppendText(msc + "\r\n");
}
private void button1_Click(object sender, EventArgs e)
{
//从txtmsg.txt中获取要发的消息
string str=txtmsg.Text.Trim();
//把要发的信息转换成UTF8文件格式的字节数组
byte[] input = System.Text.Encoding.UTF8.GetBytes(str);
byte[] arrmsgsend=new byte[input.Length+1];
arrmsgsend[0] = 0;
Buffer.BlockCopy(input, 0, arrmsgsend, 1, input.Length);
//向客户端发送消息
scoketkehu.Send(arrmsgsend);
//转出发出的信息
Mymsc("发出的消息" + str);
}
/// <summary>
/// 得到文件路径
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btselectfile_Click(object sender, EventArgs e)
{
//显示一个打开始文件的对话框
OpenFileDialog ofd = new OpenFileDialog();
//判断是否有打开文件
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtfilepath.Text=ofd.FileName;//把得到的文件路径传给text控件;
}
}
//向服务端发送文件
private void btsendfile_Click(object sender, EventArgs e)
{
//打开要发送的文件
using (FileStream file = new FileStream(txtfilepath.Text.Trim(), FileMode.Open))
{
//定义一个2M的缓存空间
byte[] byt = new byte[1024 * 1024 * 2];
//读取文件存到byt字节数组,获取所读文件长度
int length=file.Read(byt, 0, byt.Length);
//定一个可以有标识符的字节数组
byte[] arrfile = new byte[length+1];
//给标识符赋值
arrfile[0] = 1;
//复制byt数组的数据(从第0个字符开始复制),到arrfile数级内(从第1个开始写入)
Buffer.BlockCopy(byt, 0, arrfile, 1, length);
//向服务端传送数据
scoketkehu.Send(arrfile);
Mymsc("文件发送成功");
}
}
}
}
---------------------- Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------
- 黑马程序员-多线程聊天室
- 黑马程序员----网络编程UDP多线程聊天室
- 黑马程序员_多线程socket聊天室
- 黑马程序员--多线程与套接字组合:简单聊天室(1)
- 黑马程序员--多线程与套接字组合:简单聊天室(2)
- 黑马程序员—多线程聊天室(Socket介绍+源码)
- 黑马程序员-简单聊天室
- 黑马程序员-006聊天室程序
- 黑马程序员之聊天室设计
- 《黑马程序员》Udp之聊天室
- 【黑马程序员】视频拓展——多线程聊天室客户端与客户端的交互
- 黑马程序员_聊天室学习(一)
- 黑马程序员 Socket网络编程--聊天室
- 黑马程序员 多线程
- 黑马程序员:多线程
- 黑马程序员-java多线程
- 黑马程序员--java 多线程
- 黑马程序员_java多线程
- Camshift算法(2)
- 动画概述
- 向量几何在游戏编程中的使用4
- 重构36计
- 使用dbus-glib (发送signal例子)
- 黑马程序员-多线程聊天室
- 三种方法:C#获取网页内容
- Chrome的一些实用脚本(牛逼)
- 向量几何在游戏编程中的使用5
- Oracle Enterprise Pack for Eclipse 11g
- 基于SOPC的触摸屏操作
- 【矩形切割】Atlantis
- 向量几何在游戏编程中的使用6
- 用firebreath开发插件