110,533
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Shell32;
using AviFile;
namespace media
{
public partial class Show : Form
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
Thread serverThread;
Thread clientThread;
Socket serverSocket;
Socket clientSocket;
public Show()
{
InitializeComponent();
}
private Thread threadWatch = null;//负责监听客户端连接请求的线程
private Socket socketWatch = null;//负责监听的套接字
private void ServerStart()
{
IPEndPoint localipep = new IPEndPoint(IPAddress.Any, 6000);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将所创建的套接字与IPEndPoint绑定
serverSocket.Bind(localipep);
serverSocket.Listen(20);
threadWatch = new Thread(WatchConnection);
threadWatch.IsBackground = true;
threadWatch.Start();
}
void WatchConnection()
{
while (true)
{
try
{
allDone.Reset();
serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
allDone.WaitOne();
}
catch (Exception ex)
{
MessageBox.Show("listening Error: " + ex.Message);
}
}
}
//接收连接的回调函数
void Accept(IAsyncResult iar)
{
//调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信
Socket MyServer = (Socket)iar.AsyncState;
clientSocket = MyServer.EndAccept(iar);
//线程挂起
clientThread = new Thread(new ThreadStart(ReceiveData));
clientThread.IsBackground = true;
clientThread.Start();
}
}
解释:ReceiveData()是代码中实现数据传递的代码,原理是根据客户端发来的请求字符串的不同,应用switch case语句执行不同的功能,一对一可以实现的话因该不是这里的问题了~~
client端代码:
using System;
using System.IO;
using System.Drawing;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace Client
{
public partial class Form1 : Form
{
public int i = 0;
private Socket client;
private int serverport = 6000;
private IPEndPoint serverEP = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)//读取ip并连接server端
{
if (textBox1.Text.Trim() == "")
{
textBox1.Select();
return;
}
var exp = @"^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$";
Match m = Regex.Match(textBox1.Text.Trim(), exp);
if (!m.Success)
{
MessageBox.Show("IP地址格式错误!IP地址的格式为xxx.xxx.xxx.xxx(xxx为0-255)。",
"提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
textBox1.SelectAll();
textBox1.Select();
return;
}
ConnectServer(textBox1.Text.Trim());
}
private void ConnectServer(string serverIP)
{
serverEP = new IPEndPoint(IPAddress.Parse(serverIP), serverport);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(serverEP, new AsyncCallback(ConnectCallback), client);
}
private void ConnectCallback(IAsyncResult iar)
{
client = (Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
PrintStatus("已连接至服务器。");
PrintStatus("recerving...");
BeginReceive();
}
catch (Exception err)
{
PrintStatus(err.Message);
return;
}
}
解释:BeginReceive()是开始接受数据的函数,PrintStatus()是显示信息的函数。
public void BeginReceive()//调用此函数 接收文件的开始工作
{
byte[] buffer = new byte[8];
//由于long占8位字节,所以先获取前8位字节数据
IAsyncResult iar = client.BeginReceive(
buffer,
0,
buffer.Length,
SocketFlags.None,
null,
null);
int len = client.EndReceive(iar);
int offset = 0;
int length = BitConverter.ToInt32(buffer, offset); //先获取文件长度
ReceiveFile(length);
BeginReceive(); //继续接收
}
public void ReceiveFile(long filelen)
{
MemoryStream ms = new MemoryStream();
int bytesRead = 0;
long count = 0;
long filelen1 = filelen;
int filelen2 = (int)filelen1;
byte[] buffer = new byte[filelen2];
i+=1;
string i1 = Convert.ToString(i);
string fileNameTime = DateTime.Now.ToString("yyyyMMddhhmmss");
string filenameuse = i1+"-"+fileNameTime ;
while (count != filelen)
{
if (!Directory.Exists("pics/"))//如果不存在该文件夹 也就是被删掉了 就先建一个
{
System.IO.Directory.CreateDirectory("pics/");
}
bytesRead = client.Receive(buffer, buffer.Length, 0);
ms.Write(buffer, 0, bytesRead);
count += bytesRead;
if (count == bytesRead)//写进去文件夹
{
FileStream fs2 = new FileStream("pics/"+filenameuse + ".jpg", FileMode.Create);
BufferedStream bs2 = new BufferedStream(fs2);
fs2.Write(buffer, 0, bytesRead);
fs2.Flush();
fs2.Close();
}
else
{
FileStream fs2 = new FileStream("pics/"+filenameuse + ".jpg", FileMode.Append);
BufferedStream bs2 = new BufferedStream(fs2);
fs2.Write(buffer, 0, bytesRead);
fs2.Flush();
fs2.Close();
}
}
pictureBox1.ImageLocation = "pics/" + filenameuse + ".jpg";
}
我不是特别清楚memorystream与NetworkStream 在接受数据时性能的优缺点,会不会是产生这种情况的原因?还是说是在建立主客连接时出的问题。
还麻烦您不吝赐教
private void ServerStart()
{
//创建IPEndPoint实例
IPEndPoint localipep = new IPEndPoint(IPAddress.Any, 6000);
//创建一个套接字
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将所创建的套接字与IPEndPoint绑定
serverSocket.Bind(localipep);
//设置套接字为收听模式
serverSocket.Listen(20);
threadWatch = new Thread(WatchConnection);
threadWatch.IsBackground = true;//设置为后台
threadWatch.Start();// 启动线程
}
void WatchConnection()
{
while (true)
{
try
{
allDone.Reset();
serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
allDone.WaitOne();
}
catch (Exception ex)
{
MessageBox.Show("listening Error: " + ex.Message);
}
}
}
//接收连接的回调函数
void Accept(IAsyncResult iar)
{
//调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信
Socket MyServer = (Socket)iar.AsyncState;
clientSocket = MyServer.EndAccept(iar);
clientThread = new Thread(new ThreadStart(ReceiveData));
clientThread.IsBackground = true;
clientThread.Start();
allDone.Reset();
//serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
//上面这句或下面这段是不是可以避免那种情况呢呢??
threadWatch = new Thread(new ThreadStart(WatchConnection));
threadWatch.IsBackground = true;//设置为后台
threadWatch.Start();// 启动线程
}
确实您说的是我今天早上一直纠结的问题,十分感谢![/quote]
1.你代码没法确定要回转给哪个客户端
2.你的代码如果是发送的数据包发送间隔在 不频繁情况下是可以收到。但如果包发多了发快了就产生了粘包的情况,就造成你收发的数据不正确,只要不正常。Socket就异常。线程不工作。所以。。。对你的要求来说上面的代码基本不可用。建义你看看我上面发的连接的代码,他解决粘包 还有发送对象问题 。这方面那个DEMO做的比较全面了。只能帮到你这了,因为要深入跟你讲这个,说个几天都说不完,关键的是 接收字节缓冲区 与 数据包协议 以及文件的分块(你的Image文件 一般一次是发不完的,所以要分成几次分)[/quote]
你好:
十分感谢!感谢您的斧正,谢谢帮助!
private void ServerStart()
{
//创建IPEndPoint实例
IPEndPoint localipep = new IPEndPoint(IPAddress.Any, 6000);
//创建一个套接字
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将所创建的套接字与IPEndPoint绑定
serverSocket.Bind(localipep);
//设置套接字为收听模式
serverSocket.Listen(20);
threadWatch = new Thread(WatchConnection);
threadWatch.IsBackground = true;//设置为后台
threadWatch.Start();// 启动线程
}
void WatchConnection()
{
while (true)
{
try
{
allDone.Reset();
serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
allDone.WaitOne();
}
catch (Exception ex)
{
MessageBox.Show("listening Error: " + ex.Message);
}
}
}
//接收连接的回调函数
void Accept(IAsyncResult iar)
{
//调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信
Socket MyServer = (Socket)iar.AsyncState;
clientSocket = MyServer.EndAccept(iar);
clientThread = new Thread(new ThreadStart(ReceiveData));
clientThread.IsBackground = true;
clientThread.Start();
allDone.Reset();
//serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
//上面这句或下面这段是不是可以避免那种情况呢呢??
threadWatch = new Thread(new ThreadStart(WatchConnection));
threadWatch.IsBackground = true;//设置为后台
threadWatch.Start();// 启动线程
}
确实您说的是我今天早上一直纠结的问题,十分感谢![/quote]
1.你代码没法确定要回转给哪个客户端
2.你的代码如果是发送的数据包发送间隔在 不频繁情况下是可以收到。但如果包发多了发快了就产生了粘包的情况,就造成你收发的数据不正确,只要不正常。Socket就异常。线程不工作。所以。。。对你的要求来说上面的代码基本不可用。建义你看看我上面发的连接的代码,他解决粘包 还有发送对象问题 。这方面那个DEMO做的比较全面了。只能帮到你这了,因为要深入跟你讲这个,说个几天都说不完,关键的是 接收字节缓冲区 与 数据包协议 以及文件的分块(你的Image文件 一般一次是发不完的,所以要分成几次分)
public void BeginReceive()//调用此函数 接收文件的开始工作
{
byte[] buffer = new byte[8];
//由于long占8位字节,所以先获取前8位字节数据
IAsyncResult iar = client.BeginReceive(
buffer,
0,
buffer.Length,
SocketFlags.None,
null,
null);
int len = client.EndReceive(iar);
int offset = 0;
int length = BitConverter.ToInt32(buffer, offset); //先获取文件长度
ReceiveFile(length);
BeginReceive(); //继续接收
}
public void ReceiveFile(long filelen)
{
MemoryStream ms = new MemoryStream();
int bytesRead = 0;
long count = 0;
long filelen1 = filelen;
int filelen2 = (int)filelen1;
byte[] buffer = new byte[filelen2];
i+=1;
string i1 = Convert.ToString(i);
string fileNameTime = DateTime.Now.ToString("yyyyMMddhhmmss");
string filenameuse = i1+"-"+fileNameTime ;
while (count != filelen)
{
if (!Directory.Exists("pics/"))//如果不存在该文件夹 也就是被删掉了 就先建一个
{
System.IO.Directory.CreateDirectory("pics/");
}
bytesRead = client.Receive(buffer, buffer.Length, 0);
ms.Write(buffer, 0, bytesRead);
count += bytesRead;
if (count == bytesRead)//写进去文件夹
{
FileStream fs2 = new FileStream("pics/"+filenameuse + ".jpg", FileMode.Create);
BufferedStream bs2 = new BufferedStream(fs2);
fs2.Write(buffer, 0, bytesRead);
fs2.Flush();
fs2.Close();
}
else
{
FileStream fs2 = new FileStream("pics/"+filenameuse + ".jpg", FileMode.Append);
BufferedStream bs2 = new BufferedStream(fs2);
fs2.Write(buffer, 0, bytesRead);
fs2.Flush();
fs2.Close();
}
}
pictureBox1.ImageLocation = "pics/" + filenameuse + ".jpg";
}
我不是特别清楚memorystream与NetworkStream 在接受数据时性能的优缺点,会不会是产生这种情况的原因?还是说是在建立主客连接时出的问题。
还麻烦您不吝赐教[/quote]
界面卡死的原因都是因为UI线程阻塞 或者 得不到cpu的控制权
我不知道你具体代码什么样的 传视频和图片等 可能需要先压缩再传过去 接收方再解压缩 不然数据量太大[/quote]
我们的代码中视频传输的原理是先通过程序分解成一帧一帧的位图,每张十几到几十k的大小,然后再通过传图片的原理传过去。我想请教一下这种程序调试方法是什么,一直苦于没有好的调试方法。。。
还有我很想知道,怎么才能检测出不同客户端与主机是通过不同的套接字连起来的呢,我比较担心两台客户端是通过相同的套接字与主机连起来的。。。。[/quote]
1.不管传输的是什么 本质还是byte[] 像发送string一样去调试
2.参见#6 你还没搞清楚 整个流程是什么样子的[/quote]
您好!
您批评的是,我只有过c++的基础,但还没有真正动手编过这种程序,c#也是5月份才开始为了课设自学的,感谢您一直回帖,十分感谢!
就是我觉得牵扯到这种几台电脑一起调试的我觉得很模糊,而且单步总会报跨线程调用之类的错误,所以不成功。。。
我觉得流程的话我不是不清楚,就是一到计算机里面我就觉得有些模糊了。。。