求助C#大牛!!在 socket通信中,多客户端与一个服务器端异步通信时,服务器监听客户端套接字后,如何分别开启一个线程去进行数据传送??

u010684484 2013-07-15 10:11:32
小弟新人,初来报道,求各位大神指导~~

最近在做一个课设,是有关C#中socket异步通信的,要求两台以上客户端向服务器端请求传送图片和视频信息,服务器端在接到请求后分别向每个客户端发送它们需要的信息,在调试过程中,发现一对一的话可以实现基本功能,但只要多客户端的话,另一台倒是显示“已连接”,但请求后得不到回复。故猜测:是在服务器端监听并产生新线程这段代码出问题,没有把两个服务器请求区分开,即没有产生新的套接字去建立通信连接。

但只是个人臆测,还望c#大牛指导~~
现贴上我们主机端和客户端代码,请各位大牛们不吝赐教~~

server端:

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()是显示信息的函数。


以上是我们socket通信的主客端代码,请赐教~~
...全文
505 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
justlit 2013-07-27
  • 打赏
  • 举报
回复
哥们 你那个问题解决了 我是初学Socket 我做了个C#Socket通讯只能一个服务器,一个客户端通讯 也是不能和多个客户端通讯 求帮助
liajun1221 2013-07-17
  • 打赏
  • 举报
回复
引用 31 楼 liajun1221 的回复:
[quote=引用 18 楼 u010684484 的回复:] [quote=引用 17 楼 liajun1221 的回复:] 推荐使用封装好的SocketAsyncEventArgs
那是要在大改一番的节奏么?我担心现在改有点来不及了,我们手头上这个真的就改不好么。。。。 我总觉得是可以改好的,但苦于没有类似的例子,还有不知道症结所在。[/quote] 不需要 MSDN上现成的,copy出来就可以用,只需要完成自己对数据具体处理的方法就行了[/quote] 补充下,做网络通信,至少应该包含通信协议头部分,不然后面的数据很容易出错,要做好异常处理
liajun1221 2013-07-17
  • 打赏
  • 举报
回复
引用 18 楼 u010684484 的回复:
[quote=引用 17 楼 liajun1221 的回复:] 推荐使用封装好的SocketAsyncEventArgs
那是要在大改一番的节奏么?我担心现在改有点来不及了,我们手头上这个真的就改不好么。。。。 我总觉得是可以改好的,但苦于没有类似的例子,还有不知道症结所在。[/quote] 不需要 MSDN上现成的,copy出来就可以用,只需要完成自己对数据具体处理的方法就行了
u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 7 楼 u010684484 的回复:
[quote=引用 4 楼 xiaozhi_5638 的回复:] [quote=引用 3 楼 xiaozhi_5638 的回复:] Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 // ... //socket.BeginAccept(...,new AsyncCallBack(OnAccept),...); //继续侦听下一个客户端socket连入 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
漏了一行 [/quote] 这个socket侦听泵是不是就是你代码中红体字标注的那部分,对应在连上一个主客之后再继续后台监听新的连接请求?[/quote] 谢谢指导,我加进去之后可以实现了两个客户端与主机的连接及传图片。但冒昧再问您一个问题,两台机子同时要求传视频却会卡死,一台传视频另一台传点击要求传一张图片视频也会卡死,但主机这边仍显示正在传视频,客户端就会死。所以我想问您,按理说异步通信建立之后就应该两台客户端与主机应该没有什么相关行了,都是单独进行的主客操作,出现这种情况的原因会不会是客户端接收数据时产生的错误呢? 我们客户端接收用的是这两个函数:

 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 在接受数据时性能的优缺点,会不会是产生这种情况的原因?还是说是在建立主客连接时出的问题。 还麻烦您不吝赐教
请叫我卷福 2013-07-15
  • 打赏
  • 举报
回复
引用 7 楼 u010684484 的回复:
[quote=引用 4 楼 xiaozhi_5638 的回复:] [quote=引用 3 楼 xiaozhi_5638 的回复:] Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 // ... //socket.BeginAccept(...,new AsyncCallBack(OnAccept),...); //继续侦听下一个客户端socket连入 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
漏了一行 [/quote] 这个socket侦听泵是不是就是你代码中红体字标注的那部分,对应在连上一个主客之后再继续后台监听新的连接请求?[/quote] 是的 可以这样理解 说白了 就是一个while循环 关于“泵”的更多详细 请参考http://www.cnblogs.com/xiaozhi_5638/p/3167794.html 以及后一篇
u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 4 楼 xiaozhi_5638 的回复:
[quote=引用 3 楼 xiaozhi_5638 的回复:] Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 // ... //socket.BeginAccept(...,new AsyncCallBack(OnAccept),...); //继续侦听下一个客户端socket连入 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
漏了一行 [/quote] 这个socket侦听泵是不是就是你代码中红体字标注的那部分,对应在连上一个主客之后再继续后台监听新的连接请求?
请叫我卷福 2013-07-15
  • 打赏
  • 举报
回复
请参考: http://www.cnblogs.com/xiaozhi_5638/archive/2012/12/19/2824910.html 博客中第二张图 tcp通信中 服务端 专门有一个“socket侦听泵” 用来接收客户端的socket连入
u010684484 2013-07-15
  • 打赏
  • 举报
回复
回复:xiaozhi_5638 你好!我看了一下你写的,应该和我们的代码区别不是特别大,原理都应该是一样的,但我们就是两台客户端连得时候都显示已连接了,但只有一台能传数据,所以我感觉可能我的代码哪有一点小问题,比较纠结,您能稍微斧正一下么~~谢谢赐教,很感谢!
请叫我卷福 2013-07-15
  • 打赏
  • 举报
回复
引用 3 楼 xiaozhi_5638 的回复:
Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 // ... //socket.BeginAccept(...,new AsyncCallBack(OnAccept),...); //继续侦听下一个客户端socket连入 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
漏了一行
请叫我卷福 2013-07-15
  • 打赏
  • 举报
回复
Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
u010684484 2013-07-15
  • 打赏
  • 举报
回复
回复:woaidanling1314 我们刚查了一下,有一种方法是用一个数组的形式,每产生一个客户端套接字,数组中位置就++,以区别开来,但没见到类似成功的代码可以参考,目前仍在调试,你们有什么好想法么?
woaidanling1314 2013-07-15
  • 打赏
  • 举报
回复
我也遇到这样的问题了顶
u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 28 楼 kxm_2012 的回复:
你好! 谢谢了,感觉你这个帮助挺大的,挺有用,谢了~~
u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 24 楼 wyd1520 的回复:
[quote=引用 22 楼 u010684484 的回复:] [quote=引用 20 楼 wyd1520 的回复:] [quote=引用 19 楼 u010684484 的回复:] [quote=引用 16 楼 wyd1520 的回复:] 每一个Socket连接后,服务端要把 //调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信 Socket MyServer = (Socket)iar.AsyncState; clientSocket = MyServer.EndAccept(iar); 这个的 clientSocket 保存到一个列表中。 以后所有像客户端发送Socket都由这个列表中取出对应的对像发送,这样才能向指定的客户端发送信息 你要列子 http://beetle.henryfan.net/ 这个做的很不错了服务端客户端都很全,粘包处理也解决了。开源的。
你好!您说的这个貌似跟我们要求的有点出入。感觉您说的这个像是多人聊天系统,先确定对象再发内容,我们要求服务器端在监听之后就是“死”的了,只有客户端能做决定,而主机要根据客户端的决定智能的实现他们各自的要求。 感觉有点不太一样。。。不知道我说的对吗。。[/quote] 你的理解是错的。这跟多人聊天系统没关系的, 你所说的客户端相当于, Client1发送信息 ->服务端接收 ->服务端返回信息给Client1 Client2发送信息 ->服务端接收 ->服务端返回信息给Client2 Client1与Client2是没有关系的是这样子吧 好比两个Client同时发送信息了但服务端返回信息时要返回给哪个客户端。你如何区分出来。 怎么把他们要的结果返回给对应的客户端。看你上面的代码写的你是没法确定的。 所以我所说的要把Socket保存下来就是用来做这个的。 你的代码里有客户端连接后 把SOcket赋给 clientSocket 也就是你只保存了最后一个连接的对象, 也就是说只有最后那个连接的客户端 才会接收到相应的信息[/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文件 一般一次是发不完的,所以要分成几次分)[/quote] 你好: 十分感谢!感谢您的斧正,谢谢帮助!
魂之挽歌来袭 2013-07-15
  • 打赏
  • 举报
回复



u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 26 楼 dongxinxi 的回复:
你用Begin-End方法对就行了,不用去管线程分配问题,.Net负责调度 比如接收用BeginReceive EndReceive,写数据也是一样
你好! 亲呐~~我还真是从头到尾就是begin-end,但没出来的原因我觉得真是没有1个客户端socket对应一个主端socket,如上面两位大牛所说,需要建立起多个异步通信的实例~~ 谢谢赐教~~
  • 打赏
  • 举报
回复
你用Begin-End方法对就行了,不用去管线程分配问题,.Net负责调度 比如接收用BeginReceive EndReceive,写数据也是一样
请叫我卷福 2013-07-15
  • 打赏
  • 举报
回复
我没批评你啊。。。

还有我很想知道,怎么才能检测出不同客户端与主机是通过不同的套接字连起来的呢,我比较担心两台客户端是通过相同的套接字与主机连起来的。。。。

这个问题参见你发的第二贴 我发的一张图 两个客户端不可能使用同一个socket 服务端都有与之对应的socket的


本拉灯 2013-07-15
  • 打赏
  • 举报
回复
引用 22 楼 u010684484 的回复:
[quote=引用 20 楼 wyd1520 的回复:] [quote=引用 19 楼 u010684484 的回复:] [quote=引用 16 楼 wyd1520 的回复:] 每一个Socket连接后,服务端要把 //调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信 Socket MyServer = (Socket)iar.AsyncState; clientSocket = MyServer.EndAccept(iar); 这个的 clientSocket 保存到一个列表中。 以后所有像客户端发送Socket都由这个列表中取出对应的对像发送,这样才能向指定的客户端发送信息 你要列子 http://beetle.henryfan.net/ 这个做的很不错了服务端客户端都很全,粘包处理也解决了。开源的。
你好!您说的这个貌似跟我们要求的有点出入。感觉您说的这个像是多人聊天系统,先确定对象再发内容,我们要求服务器端在监听之后就是“死”的了,只有客户端能做决定,而主机要根据客户端的决定智能的实现他们各自的要求。 感觉有点不太一样。。。不知道我说的对吗。。[/quote] 你的理解是错的。这跟多人聊天系统没关系的, 你所说的客户端相当于, Client1发送信息 ->服务端接收 ->服务端返回信息给Client1 Client2发送信息 ->服务端接收 ->服务端返回信息给Client2 Client1与Client2是没有关系的是这样子吧 好比两个Client同时发送信息了但服务端返回信息时要返回给哪个客户端。你如何区分出来。 怎么把他们要的结果返回给对应的客户端。看你上面的代码写的你是没法确定的。 所以我所说的要把Socket保存下来就是用来做这个的。 你的代码里有客户端连接后 把SOcket赋给 clientSocket 也就是你只保存了最后一个连接的对象, 也就是说只有最后那个连接的客户端 才会接收到相应的信息[/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文件 一般一次是发不完的,所以要分成几次分)
u010684484 2013-07-15
  • 打赏
  • 举报
回复
引用 21 楼 xiaozhi_5638 的回复:
[quote=引用 14 楼 u010684484 的回复:] [quote=引用 11 楼 xiaozhi_5638 的回复:] [quote=引用 9 楼 u010684484 的回复:] [quote=引用 7 楼 u010684484 的回复:] [quote=引用 4 楼 xiaozhi_5638 的回复:] [quote=引用 3 楼 xiaozhi_5638 的回复:] Server: socket.beginAccept(...,new AsyncCallBack(OnAccept),..); //异步侦听socket连入 private void OnAccept(IAsyncResult ar) { Socket s = socket.EndAccept(ar); s.beginReceive(...,new AsyncCallBack(OnReceive),s); //异步接收数据 // ... //socket.BeginAccept(...,new AsyncCallBack(OnAccept),...); //继续侦听下一个客户端socket连入 } private void OnReceive(IasyncResult ar) { // 处理数据 } 每连入一个客户端socket 就会BeginReceive
漏了一行 [/quote] 这个socket侦听泵是不是就是你代码中红体字标注的那部分,对应在连上一个主客之后再继续后台监听新的连接请求?[/quote] 谢谢指导,我加进去之后可以实现了两个客户端与主机的连接及传图片。但冒昧再问您一个问题,两台机子同时要求传视频却会卡死,一台传视频另一台传点击要求传一张图片视频也会卡死,但主机这边仍显示正在传视频,客户端就会死。所以我想问您,按理说异步通信建立之后就应该两台客户端与主机应该没有什么相关行了,都是单独进行的主客操作,出现这种情况的原因会不会是客户端接收数据时产生的错误呢? 我们客户端接收用的是这两个函数:

 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月份才开始为了课设自学的,感谢您一直回帖,十分感谢! 就是我觉得牵扯到这种几台电脑一起调试的我觉得很模糊,而且单步总会报跨线程调用之类的错误,所以不成功。。。 我觉得流程的话我不是不清楚,就是一到计算机里面我就觉得有些模糊了。。。
加载更多回复(13)

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧