求助C#大牛!!在 socket通信中,多客户端与一个服务器端异步通信时,服务器监听客户端套接字后,如何分别开启一个线程去进行数据传送??
小弟新人,初来报道,求各位大神指导~~
最近在做一个课设,是有关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通信的主客端代码,请赐教~~
[解决办法]
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
[解决办法]
1.你代码没法确定要回转给哪个客户端
2.你的代码如果是发送的数据包发送间隔在 不频繁情况下是可以收到。但如果包发多了发快了就产生了粘包的情况,就造成你收发的数据不正确,只要不正常。Socket就异常。线程不工作。所以。。。对你的要求来说上面的代码基本不可用。建义你看看我上面发的连接的代码,他解决粘包 还有发送对象问题 。这方面那个DEMO做的比较全面了。只能帮到你这了,因为要深入跟你讲这个,说个几天都说不完,关键的是 接收字节缓冲区 与 数据包协议 以及文件的分块(你的Image文件 一般一次是发不完的,所以要分成几次分)