C# C/S 客户端与服务器端交户
服务器端代码:
namespace Server
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form3());
Application.Run(new ServerForm());
}
}
}
public void run()
{
ipIpep = new IPEndPoint(IPAddress.Any,6666); //服务器从6666端口接收客户端的登陆请求
receiveUdpClient = new UdpClient(ipIpep);
sendUdpClient = new UdpClient();
receiveState = new UdpState();
receiveState.udpClient = receiveUdpClient;
receiveState.ipEndPoint = ipIpep;
sendState = new UdpState();
sendState.udpClient = sendUdpClient;
sendState.ipEndPoint = remoteIpep;
ReceiveMsg();
}
public void ReceiveMsg()
{
try
{ //循环接受客户端发过来的请求并响应
while (true)
{
lock (this)
{
IAsyncResult iar = receiveUdpClient.BeginReceive(new AsyncCallback(ReceiveCallback),receiveState);
receiveDone.WaitOne();
Thread.Sleep(100);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
MessageBox.Show(ex.Message);
}
}
private void ReceiveCallback(IAsyncResult iar)
{
UdpState receiveState = iar.AsyncState as UdpState;
if (iar.IsCompleted)
{
data = receiveState.udpClient.EndReceive(iar,ref receiveState.ipEndPoint);
int i = 0;
///取出命令
for (i = 0; i < leng; i++)
{
if (Convert.ToInt32(data[i]) == 0) //寻找请求中的有效字符的最终位置
break;
}
byte[] cmdbyte = new byte[i];
for (int k = 0; k < i; k++)
{
cmdbyte[k] = data[k];
}
commandStr = Encoding.ASCII.GetString(cmdbyte);
MessageBox.Show(commandStr,"kkk");
///取出数据
buff = new byte[data.Length - leng];
for (int j = 0; j < data.Length - leng; j++)
buff[j] = data[leng + j];
memStream = new MemoryStream(buff);
memStream.Seek(0, SeekOrigin.Begin);
obj = formatter.Deserialize(memStream);
memStream.Close();
if (obj != null && obj is User)
user = (User)obj;
remoteIpep = new IPEndPoint(receiveState.ipEndPoint.Address, 8888);
handleMsg(commandStr);
receiveDone.Set();
}
}
//处理消息
private void handleMsg(String msg)
{
switch (msg)
{
case "Login":
string sqlLogin = "SELECT * FROM tb_users where 用户名='" + user.Username + "' and 密码='" + user.Password + "'and 启用标志=1";
multipleDB.getcon();
SqlDataReader reader = multipleDB.getread(sqlLogin);
if(contactWithClient==null)
contactWithClient = new ContactWithClient();
if (reader.HasRows) //身份验证成功
{
///将登陆日志插入用户日志中
string sqlLoginJournal = "INSERT INTO tb_journal(用户名,操作类型ID,操作时间,描述,审计状态) VALUES('" + user.Username + "'," + 1 + ",'" + DateTime.Now + "','登陆了用户客户端'," + 0 + ")";
multipleDB.getcon();
multipleDB.getcom(sqlLoginJournal);
contactWithClient.User = user;
Sthread = new Thread(new ThreadStart(contactWithClient.ReceiveMsg));
Sthread.Start();
///将用户的详细信息查出来,返回给客户端
string sqluser = "SELECT 姓名,部门名称 FROM tb_users,tb_department where 用户名='" + user.Username + "' AND tb_users.部门ID=tb_department.部门ID";
multipleDB.getcon();
DataTable dt = new DataTable();
dt = multipleDB.getdt(sqluser);
user.Name=dt.Rows[0][0].ToString();
user.Department=dt.Rows[0][1].ToString();
info = Encoding.ASCII.GetBytes("LoginSuccess");
byte[] cmd = new byte[20];
for (int i = 0; i < info.Length; i++)
{
cmd[i] = info[i];
}
memStream = new MemoryStream();
formatter.Serialize(memStream, user);
byte[] data = memStream.ToArray(); //将User对象发送给客户端
memStream.Flush();
memStream.Close();
byte[] buffer = new byte[cmd.Length + data.Length];
Array.Copy(cmd, 0, buffer, 0, cmd.Length);
Array.Copy(data, 0, buffer, cmd.Length, data.Length);
contactWithClient.SendMsg(buffer, buffer.Length, remoteIpep);
contactWithClient.remoteEp(remoteIpep);
}
else //身份验证失败
{
info = Encoding.ASCII.GetBytes("LoginFail");
contactWithClient.SendMsg(info, info.Length,remoteIpep);
}
reader.Close();
break;
}
}
客户端退出后,若服务器不退出,等上一段时间后红色代码就会出错,出错信息:由于系统缓存空间不足或列队已满,不能执行套接字上的操作
[解决办法]
首先你要搞清楚你使用的那个协议!如果是TCP/IP 协议的话必须指定端口因为是点对点的通讯,如果是UDP 就不需要指定客户端端口使用广播即可。看你的代码好像是前者!
[解决办法]
你的锁 lock 用的有问题你应该是锁住 一个请求的对象 但是你这里lock(this)不知道想干什么。
你可以使用队列 把接收的请求放在队列里面然后逐个处理!
[解决办法]
参考:http://www.cnblogs.com/zhili/archive/2012/08/25/TCP.html
[解决办法]
UDP 协议服务器的端口肯定要固定啊 要不然就惨了 客户端端口不固定 哪服务器就变成一般的客户端了 那就不存在服务器这一说了!UDP虽然是无链接的 但是服务器地址是固定的啊.
[解决办法]
LZ
你可以到CSDN 中下一个源码看看!