winform开发里的简单socket消息提醒问题,求指教!

chengwen2402163 2011-02-22 02:00:08
项目需要做一个类似于QQ的消息提醒,当数据库向指定客户发送记录时,通过socket向客户端发送消息提醒,相当于广播这种形式,但是我写了下面的源码,在点击服务端的发送按钮后却没有反应...请高手指点
发送端(Server)源吗:

public partial class Form1 : Form
{
private IPEndPoint ep;
private Socket soc;
private Thread myThread;
private byte[] bytes;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
ep = new IPEndPoint(IPAddress.Parse("192.168.1.106"), 9050);
soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
soc.Bind(ep);
soc.Listen(50);


}

private void Recive()
{
try
{
//while (true)//这里while注释的原因是想手动发而不用无限循环
//{
try
{
//Socket mySocket = soc.Accept();
bytes = Encoding.Default.GetBytes(TextBox1.Text);
soc.Send(bytes);
Thread.Sleep(2000);
}
catch (Exception ex)
{

}
//}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

private void button1_Click(object sender, EventArgs e)
{
myThread = new Thread(new ThreadStart(Recive));
myThread.Name = "b";
myThread.Start();
}

}


接收端(Client)源码:

public partial class Form1 : Form
{
private IPEndPoint enLoap;
private Socket mySocket;
private Thread myThread = null;
private EndPoint ep;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
enLoap = new IPEndPoint(IPAddress.Parse("192.168.1.106"), 9050); ;
mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mySocket.Connect(enLoap);

ep = (EndPoint)enLoap;
myThread = new Thread(new ThreadStart(Recive));
myThread.Name = "c";
myThread.Start();
}

private void Recive()
{
try
{
while (true)
{
try
{
if (mySocket == null)
{
Thread.Sleep(1000);
//continue;
}
else
{
if (listBox1.Items.Count > 10)
{
listBox1.Items.Clear();
}
byte[] b = new byte[1024];
int size = mySocket.Receive(b);
string strbuff = Encoding.Default.GetString(b, 0, size);
if (!String.IsNullOrEmpty(strbuff))
{
listBox1.Items.Add("收到消息: " + strbuff);
}

}
}
catch (Exception ex)
{

}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}


private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (myThread != null & myThread.ThreadState != ThreadState.Unstarted && myThread.ThreadState != ThreadState.Stopped)
{
myThread.Abort();
}
if (mySocket != null)
{
mySocket.Close();
}

}
}

...全文
240 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lizhibin11 2011-02-22
  • 打赏
  • 举报
回复
这些都仅仅是雏形,可能也算不上雏形。socket编程中线程同步、分析数据包、发送队列这些,对于最简单的数据也是必要的。实在不行你用wcf的net.tcp协议算了,这个是很简单的。你下载这个示例看看吧:
http://files.cnblogs.com/wayfarer/ChatRoom.zip
lizhibin11 2011-02-22
  • 打赏
  • 举报
回复
你可以保存socket套接字到集合里,如果采用同步方式,服务端应该有一个线程在循环accept,返回后将socket放到集合里。当发送的时候,遍历集合中的socket执行send就可以了。
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lizhibin11 的回复:]
accept是一个阻塞方法,当有客户端连接时,会返回结果,同样receive也是阻塞方法。你在每次发送前accept没有必要,因为该客户端并没有第二次连接服务器。基于tcp的socket,对每个客户端accept后的连接可以多次发送和接收。
TCP是基于连接的,UDP是无连接的,send是tcp的,sendto是udp的。
http://msdn.microsoft.com/zh-cn/lib……
[/Quote]
也就是服务端无限次的向客户端手动发送信息,
也许我该把两端都看成客户端,然后做一服务端作消息中转,不过觉得一个提醒这样做有点大材小用的感觉.

大哥,你觉得呢.
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lizhibin11 的回复:]
accept是一个阻塞方法,当有客户端连接时,会返回结果,同样receive也是阻塞方法。你在每次发送前accept没有必要,因为该客户端并没有第二次连接服务器。基于tcp的socket,对每个客户端accept后的连接可以多次发送和接收。
TCP是基于连接的,UDP是无连接的,send是tcp的,sendto是udp的。
http://msdn.microsoft.com/zh-cn/lib……
[/Quote]
嗯,发现我的代码行不通,因为server要使用手动广播信息,不能使用while,在客户端连接的时候用accept,但第二次发信息的时候不能accept,在accept之前又没办法知道是否有新的客户端连接,就算知道,也只能对新的客户端发消息,而之前的客户端都没反应.唉...
lizhibin11 2011-02-22
  • 打赏
  • 举报
回复
accept是一个阻塞方法,当有客户端连接时,会返回结果,同样receive也是阻塞方法。你在每次发送前accept没有必要,因为该客户端并没有第二次连接服务器。基于tcp的socket,对每个客户端accept后的连接可以多次发送和接收。
TCP是基于连接的,UDP是无连接的,send是tcp的,sendto是udp的。
http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.aspx这是msdn关于socket类和tcp以及udp的描述,你参考一下。
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 lizhibin11 的回复:]
系统不会因为包简单就自动避免粘包或者一次接收到一个完整的包,至少需要定义包的长度。你先解决建立连接的问题,其它情况在真正测试时才会发觉。推荐一个blog,是陈硕的c++ socket和多线程编程,http://www.cnblogs.com/Solstice/
[/Quote]
嗯,谢谢了.

private void Recive()
{
try
{
Socket mySocket = soc.Accept();
bytes = Encoding.Default.GetBytes("现在时间: " + this.textBox1.Text);
mySocket.SendTo(bytes, ep);

}
catch (Exception ex)
{

}
finally
{

} }

我修改了server的revive方法,但只能保证第一次发送成功,后续点击按钮发送就收不到了.
laladai 2011-02-22
  • 打赏
  • 举报
回复
是没有accept()方法,都没接受哪来会有反应
通常有连接建立的时候都要建立一个新的线程,特别是在同步操作情况下,不然主线程会一直处于阻塞状态。
lizhibin11 2011-02-22
  • 打赏
  • 举报
回复
系统不会因为包简单就自动避免粘包或者一次接收到一个完整的包,至少需要定义包的长度。你先解决建立连接的问题,其它情况在真正测试时才会发觉。推荐一个blog,是陈硕的c++ socket和多线程编程,http://www.cnblogs.com/Solstice/
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 lizhibin11 的回复:]
你的服务端程序没有accept,实际并未建立连接,这是不能接收的原因。
除此之外,这两段程序问题挺多的,一个是没有必要的sleep,一个是本身socket有基于IO的异步操作,专门建立处理器线程去发送完全没有必要,单就发送来说,同步也是完全可以的,再一个就是发送和接收时,没有定义约定,因为接收的时候,很多时候一次接收到的并不是一个完整的包,需要检查合并。
[/Quote]
定义约定?是什么意思呢?
这里发送的包就很简单,所以没有考虑完整性.
lizhibin11 2011-02-22
  • 打赏
  • 举报
回复
你的服务端程序没有accept,实际并未建立连接,这是不能接收的原因。
除此之外,这两段程序问题挺多的,一个是没有必要的sleep,一个是本身socket有基于IO的异步操作,专门建立处理器线程去发送完全没有必要,单就发送来说,同步也是完全可以的,再一个就是发送和接收时,没有定义约定,因为接收的时候,很多时候一次接收到的并不是一个完整的包,需要检查合并。
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sj97a007 的回复:]
没用过TCP,UDP就好办了,帮顶
[/Quote]
UDP和TCP有什么不同呢,欢迎发表啊.呵
枪牌 2011-02-22
  • 打赏
  • 举报
回复
没用过TCP,UDP就好办了,帮顶
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
chengwen2402163 2011-02-22
  • 打赏
  • 举报
回复
求指点,求解答,求合体

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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