c#聊天程序,客户端和服务器,100分,只有这么多

1.服务器需要维护在线客户端列表吗?都需要哪些信息?2.使用udp还是tcp?客户端一直与服务器保持连接吗?3.客户端之间如何通信?通过服务器转发还是自己连接?两种方式有... 1.服务器需要维护在线客户端列表吗?都需要哪些信息?
2.使用udp还是tcp? 客户端一直与服务器保持连接吗?
3.客户端之间如何通信?通过服务器转发还是自己连接?两种方式有什么优缺点?
4.局域网和外网之间通信有影响吗?需要写特别的代码吗?
5.若要开发一个聊天程序,有什么需要注意的?
希望可以讲的详细些。
怎样可以做到通信不受局域网和Internet的影响(即局域网可以和外网通信不受影响)?
直接一方监听端口,一方连接可以吗?
监听端口的一方若在局域网,没有独立ip怎么办?
展开
 我来答
老级幸1286
2009-12-10 · TA获得超过511个赞
知道小有建树答主
回答量:756
采纳率:0%
帮助的人:381万
展开全部
1: 能唯一标识用户就行。
2:我一般使用Tcp,Tcp比UDP完整,但速度上比UDP差。
3:Socket建立通讯,客户端与客户端可以直连。
4:不用。
5:没什么注意的,就是要做到以下几步。
(1):建立Socket,
(2):绑定端口,IP
(3):监听
(4):连接。
(5):收发数据。

下面是实例。
//服务器
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Reflection;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace msgServer
{
public partial class frmServer : Form
{
private Socket socket;
private IPAddress myIP;
private IPEndPoint endPoint;
private int point;
private Socket clientSocket;
private Assembly ass = null;
private System.IO.Stream stream = null;
private System.Media.SoundPlayer pl;
private string txt;
private byte[] bs = new byte[512];
public frmServer()
{
InitializeComponent();
ass = Assembly.GetExecutingAssembly();
stream = ass.GetManifestResourceStream("msgServer.msg.wav");
pl = new System.Media.SoundPlayer(stream);
}

//字体选择
private void btnFont_Click(object sender, EventArgs e)
{
FontDialog font = new FontDialog();
font.ShowEffects = true;
font.ShowColor = true;
font.MinSize = 12;
font.Font = new Font("楷体_GB2312", 18, FontStyle.Bold);
font.Color = Color.Blue;

if (font.ShowDialog() == DialogResult.OK)
{
rtxtSend.Font = font.Font;
rtxtSend.ForeColor = font.Color;
}

}

//开始监听
private void btnStart_Click(object sender, EventArgs e)
{
System.Threading.Thread th1 = new System.Threading.Thread(ToConnect);
th1.Start();
}

//去连接
private void ToConnect()
{
try
{
myIP = IPAddress.Parse(txtIP.Text.Trim());//IP
point = Convert.ToInt32(txtPoint.Text.Trim());//Point
endPoint = new IPEndPoint(myIP, point); //终端

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);//绑定
socket.Listen(3); //最多3人同时连接

lblStatus.Text = "服务器已经运行...";

clientSocket = socket.Accept();//等待接受
//连接上时
if (clientSocket.Connected)
{
lblStatus.Text = "已经建立连接.";

while (true)
{
try
{
clientSocket.Receive(bs, bs.Length, 0);
pl.Play();
rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));
}
catch { lblStatus.Text = "连接已经断开."; }
}
}
}
catch { txtIP.Focus(); txtIP.SelectAll(); MessageBox.Show("IP error OR Point error"); }
}

//停止监听
private void btnStop_Click(object sender, EventArgs e)
{
try
{
socket.Close(3);
lblStatus.Text = "监听已经停止.";
}
catch
{
lblStatus.Text = "目前未建立连接.";
}
}

private void frmServer_KeyPress(object sender, KeyPressEventArgs e)
{

}

private void frmServer_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))
{
btnSend.PerformClick();//单击发送
}
}

//发送消息
private void btnSend_Click(object sender, EventArgs e)
{
if (rtxtSend.Text.Trim() == "")
return;
else if (rtxtSend.Text.Trim().ToLower() == "clear()")
{
rtxtMsg.Clear();
rtxtSend.Text = "";
return;
}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[zoom(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
int size = Convert.ToInt32(str.Substring(str.LastIndexOf('(') + 1,
str.IndexOf(')') - str.LastIndexOf('(') - 1));
rtxtMsg.Font = new Font("宋体", size,FontStyle.Bold);
return;
}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[down(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
string size = str.Substring(str.LastIndexOf('(') + 1,str.IndexOf(')') - str.LastIndexOf('(') - 1);

if (Convert.ToInt32(size) > rtxtMsg.Text.Length)
return;

}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[up(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
string size = str.Substring(str.LastIndexOf('(') + 1,str.IndexOf(')') - str.LastIndexOf('(') - 1);

}
else if (rtxtSend.Text.Trim().ToLower() == "exit(0)")
{
this.Close();
return;
}

try
{
byte[] bs = new byte[512];
string user = null;
if (txtUser.Text.Trim() == "在此输入你的名字" || txtUser.Text.Trim() == "")
{
user = "我";
bs = Encoding.Unicode.GetBytes(string.Format("对方说:({0})\r\n{1}\r\n",DateTime.Now.ToString(), rtxtSend.Text.Trim()));
}
else
{
bs = Encoding.Unicode.GetBytes(string.Format("{0}说:({1})\r\n{2}\r\n", txtUser.Text.Trim(),DateTime.Now.ToString(), rtxtSend.Text.Trim()));
user = txtUser.Text.Trim();
}
clientSocket.Send(bs, bs.Length, 0);//发送
txt = string.Format("{0}说:({1})\r\n{2}\r\n", user, DateTime.Now.ToString(),rtxtSend.Text.Trim());
int tempLen = rtxtMsg.Text.Length;
rtxtMsg.AppendText(txt);
rtxtMsg.Select(tempLen, txt.Length);
rtxtMsg.SelectionFont = new Font("宋体", 10);
rtxtMsg.SelectionColor = Color.Red;
rtxtSend.Clear();
}
catch { MessageBox.Show("未建立连接,无法发送数据!"); }
}

//关闭Socket
private void frmServer_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
//关闭连接
socket.Close(3);
}
catch (Exception) { }
finally
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == Application.ProductName)
p.Kill();
}
}
}

private void frmServer_Load(object sender, EventArgs e)
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == Application.ProductName)//已经启动
{
if (p.Id != Process.GetCurrentProcess().Id)//不是当前进程
{
p.Kill();
}
}
}
}

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
this.TopMost = checkBox1.Checked;
}
}
}

//客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace smgClient
{
public partial class frmClient : Form
{
private IPAddress IP;//ip
private EndPoint endpoint;//point
private Socket socket;//socket
private System.IO.Stream stream = null;
private System.Reflection.Assembly ass = null;
private System.Media.SoundPlayer pl = null;
private string txt;
private byte[] bs = new byte[512];

public frmClient()
{
InitializeComponent();
ass = System.Reflection.Assembly.GetExecutingAssembly();
stream = ass.GetManifestResourceStream("smgClient.msg.wav");
pl = new System.Media.SoundPlayer(stream);
}

//请求连接
private void btnRequestConnect_Click(object sender, EventArgs e)
{
System.Threading.Thread th = new System.Threading.Thread(this.ToConnect);
th.Start();
}

//连接服务器
private void ToConnect()
{
try
{
IP = IPAddress.Parse(txtIP.Text.Trim());
int point = Convert.ToInt32(txtPoint.Text.Trim());
endpoint = new IPEndPoint(IP, point);
//建立Socket
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//建立连接
socket.Connect(endpoint);
//连接成功
lblStatus.Text = "连接成功.";

while (true)
{
socket.Receive(bs, bs.Length, 0);
pl.Play();
rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));
}
}
catch (FormatException)
{ MessageBox.Show("IP error OR Point error"); }
catch (ArgumentNullException)
{ MessageBox.Show("IP error OR Point error"); }
catch (Exception)
{
lblStatus.Text = "连接失败,原因: 服务器已停止.";
}
}

//字体
private void btnFont_Click(object sender, EventArgs e)
{
FontDialog font = new FontDialog();
font.ShowEffects = true;
font.ShowColor = true;
font.MinSize = 12;
font.Font = new Font("楷体_GB2312", 18, FontStyle.Bold);
font.Color = Color.Blue;

if (font.ShowDialog() == DialogResult.OK)
{
rtxtSend.Font = font.Font;
rtxtSend.ForeColor = font.Color;
}
}

//关闭连接
private void btnCloseConnect_Click(object sender, EventArgs e)
{
try
{
socket.Close();
lblStatus.Text = "连接已经关闭.";
}
catch
{
lblStatus.Text = "目前未建立连接.";
}
}

//发送消息
private void btnSend_Click(object sender, EventArgs e)
{
if (rtxtSend.Text.Trim() == "")
return;
else if (rtxtSend.Text.Trim().ToLower() == "clear()")
{
rtxtMsg.Clear();
rtxtSend.Text = "";
return;
}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[zoom(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
int size = Convert.ToInt32(str.Substring(str.LastIndexOf('(') + 1,
str.IndexOf(')') - str.LastIndexOf('(') - 1));
rtxtMsg.Font = new Font("宋体", size, FontStyle.Bold);
return;
}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[down(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
string size = str.Substring(str.LastIndexOf('(') + 1, str.IndexOf(')') - str.LastIndexOf('(') - 1);

if (Convert.ToInt32(size) > rtxtMsg.Text.Length)
return;

}
else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[up(]+[\d]+[)]$"))
{
string str = rtxtSend.Text.ToLower();
string size = str.Substring(str.LastIndexOf('(') + 1, str.IndexOf(')') - str.LastIndexOf('(') - 1);

}
else if (rtxtSend.Text.Trim().ToLower() == "exit(0)")
{
this.Close();
return;
}

try
{
byte[] bs = new byte[512];
string user = null;
if (txtUser.Text.Trim() == "在此输入你的名字" || txtUser.Text.Trim() == "")
{
user = "我";
bs = Encoding.Unicode.GetBytes(string.Format("对方说:({0})\r\n{1}\r\n", DateTime.Now.ToString(),rtxtSend.Text.Trim()));
}
else
{
bs = Encoding.Unicode.GetBytes(string.Format("{0}说:({1})\r\n{2}\r\n", txtUser.Text.Trim(),DateTime.Now.ToString(),rtxtSend.Text.Trim()));
user = txtUser.Text.Trim();
}

socket.Send(bs, bs.Length, 0);//发送

txt = string.Format("{0}说:({1})\r\n{2}\r\n", user, DateTime.Now.ToString(), rtxtSend.Text.Trim());
int tempLen = rtxtMsg.Text.Length;
rtxtMsg.AppendText(txt);
rtxtMsg.Select(tempLen, txt.Length);
rtxtMsg.SelectionFont = new Font("宋体", 10);
rtxtMsg.SelectionColor = Color.Red;
rtxtSend.Clear();
}
catch(Exception ex)
{ MessageBox.Show("连接尚未建立!无法发送数据!" + ex.Message); }
}

//避开打开多个
private void frmClient_Load(object sender, EventArgs e)
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == Application.ProductName)//有进程
{
if (p.Id != Process.GetCurrentProcess().Id)//不是当前进程
{
p.Kill();
}
}
}
}

private void frmClient_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
socket.Close();
}
catch(Exception) { }
finally
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == Application.ProductName)
p.Kill();
}
}
}

private void frmClient_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))
{
btnSend.PerformClick();
}
}

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
this.TopMost = checkBox1.Checked;
}
}
}
恒拓高科
2024-05-28 广告
恒拓高科提供即时通讯开发服务,全程一对一在线服务,快速集成接入app,无需研发团队,即可让App实现音视频聊天功能,可免费试用。im即时通讯就选WorkPlus,高科恒拓高科IM稳定,功能也多。是国内做即时通讯的企业之一,在使用的整个过程都... 点击进入详情页
本回答由恒拓高科提供
旁笑槐NH
2009-12-09 · TA获得超过2545个赞
知道大有可为答主
回答量:2686
采纳率:0%
帮助的人:2854万
展开全部
1.要,IP,端口,客户端的用户列表,最后连接时间
2.我觉得udp比较好,每次通讯也就是发个信息,用tcp每q一次就开/关一次连接太损了。
3.因为服务端有客户端的列表,因此可以做个复合决策:
a。都在同一个本地网,直接通讯
b。在不同的本地网,服务器转发
c。有一方或双发都在公网,直接通讯/服务器转发(如果要保存聊天记录)这个其实是QQ的策略,我觉得挺好的。
4.有影响,可以用3的策略,不建议用NAT,用NAT的话TCP没法用
5.那就太多了,说不完。。。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
百度网友bb2ba868f
2009-12-09 · TA获得超过863个赞
知道小有建树答主
回答量:330
采纳率:0%
帮助的人:304万
展开全部
1.需要维护在线列表,因为用户信息的验证时在服务器端,验证成功后,服务器需要获取客户端的ip,方便后面得通信,加入到服务器端得在线用户列表中。
2.我觉得还是用tcp好,可以确保信息按正确的顺序全部到达。在服务器端需要隔一段事件扫描一下扫描一下客户机的某个端口是否开启,如果端口关闭说明用户已经下线了,这时候可以从服务器端的在线列表中将其删除。和该用户相关的好友也可以从服务器端晓得该好友下线了。
3.我觉得客户端之间还是直接通信好。
4.肯定要有影响,一般都是在局域网做的。如果要做成像QQ那样在广域网用的聊天程序,还要涉及内网IP到外网IP地址的转换,这就很复杂了,没得一点技术是不行的。
5.建议装一个虚拟机,这样可以模拟两台机器通信。好好学一下c#中和网络通信有关的类。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
G洋葱头G
2009-12-09 · TA获得超过115个赞
知道答主
回答量:64
采纳率:0%
帮助的人:0
展开全部
不管用什么语言写聊天程序原理都一样.首先你要弄清楚你想做的是局域网的还是公共网络的聊天软件.

我下面就依次回答你的问题
1.服务器需要维护在线客户端列表吗?都需要哪些信息?
当然需要,一般需要记录客户端的IP.在线时间.客户的称呼.状态等

2使用udp还是tcp? 客户端一直与服务器保持连接吗
其实都可以.如果想保证信息的准确性还是TCP吧.至于是否需要客户端和服务器一直保持连接.如果简单一点就直接服务器转发客户端的信息.这个设计很简单.但是效率很差..复杂点但效率高点的就是NAT穿越技术,就是流行的P2P技术.你可以去看看相关资料.这个就不需要服务器一直和客户端连接.只起一个牵引作用.

3.客户端之间如何通信?通过服务器转发还是自己连接?两种方式有什么优缺点
上面已经回答了

4.局域网和外网之间通信有影响吗?需要写特别的代码吗?
同上

5.若要开发一个聊天程序,有什么需要注意的
注意的很多。首先必须要注意服务器和客户端尽量无漏洞.还有就是选择一个适合自己的网络模型.
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
ebread
2009-12-13 · 超过28用户采纳过TA的回答
知道答主
回答量:48
采纳率:0%
帮助的人:64.8万
展开全部
其实现在最简单的方法是用WCF的回调服务,这样和服务器可以保持双向通信,至于用什么通道,WCF配置一下就可以了,只能说十分方便了。

可参考一下MSDN的.NetFrameWork节下的WCF节点
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(4)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式