
---基于TCP的点对点即时通信工具
姓名:杨祺鹏
班级:191072
学号:20071000566
指导老师:梁庆中
一.设计题目及设计目标
1.设计题目
题目:实现一个基于网络的应用
要求:利用TCP或UDP完成联网通信,并在此基础上完成数据应用。
2.设计目标
这个软件实现的功能主要包括局域网内的点对点聊天(基本功能),局域网内搜索IP并显示,搜索任意IP段并显示。应用的主要范围面向局域网。
二.设计的思路
1.选用语言:C#
2.使用的主要技术:TcpClient,thread(线程)
3.功能结构图。
三.设计的实现
程序流程图:
连接不成功
不为空
为空
连接成功
继续聊天
程序结束
1.获取本机IP模块
使用的C#的IPHOSTENTRY和IPADDRESS两个类
string hostname1 = Dns.GetHostName();
IPHostEntry myentry = Dns.GetHostByName(hostname1);
IPAddress myaddress = new IPAddress(myentry.AddressList[0].Address);
string myip = myaddress.ToString();
this.localip.Text = myip;
用已经获取的本机的名字来获取本机的IP。
2.获取局域网IP
int ipdot = myip.LastIndexOf('.');
myip = myip.Substring(0,ipdot+1);
string aa = "0";//获取本机的IP后,获取最后一个.的位置,并且将这个.后面的数据替换成0和255,实现从局域网0-255的搜索
string bb = "255";
string startip = myip + aa;
string endip = myip + bb;
this.ipstart.Text = startip;
this.ipend.Text = endip;
3.搜索指定IP段的IP地址
对输入的IP段进行搜索,
string ipcur = this.ipstart.Text;
int ipdot = ipcur.LastIndexOf('.');
string ippre = ipcur.Substring(0,ipdot+1);
for (int i = 0; i <= 3;i++ )
{
MessageBox.Show("开始搜索");
string scanip = ippre + i.ToString();
IPAddress myscanip = IPAddress.Parse(scanip);
IPHostEntry myscanhost = null;
try
{
myscanhost = Dns.GetHostByAddress(myscanip);
}
catch
{
continue;
}
if (myscanhost.HostName != null)
{
MessageBox.Show("搜索到一个结果");
this.ipbox.Items.Add("可用IP:");
this.ipbox.Items.Add(scanip);
this.ipbox.Items.Add("此IP的主机名:");
this.ipbox.Items.Add(myscanhost.HostName);
}
运行截图:
4.在程序启动时同时启动另一个线程作为服务器
C/S模式都有服务器和客户端之分,在这个程序中服务器端被简化了,服务器程序不具有主动的功能,只能对端口进行监听并且修改主进程的控件。
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
Thread server = new Thread(new ThreadStart(serverfuntion));
server.IsBackground = true;
server.Start();
}
private void serverfuntion()
{
DateTime dt = new DateTime();
dt = DateTime.Now;
if (this.scanedip.Text != null)
{
TcpListener mylis = new TcpListener(IPAddress.Any, 51888);
mylis.Start();
while (true)
{
TcpClient mytcp = new TcpClient();
mytcp = mylis.AcceptTcpClient();// MessageBox.Show("连接建立成功!");
NetworkStream mystream = mytcp.GetStream();
StreamReader sr = new StreamReader(mystream); // MessageBox.Show("流建立成功!");
string received = "";
received = sr.ReadToEnd();// MessageBox.Show("消息接受成功!");
if (received != null)
{
this.messagegeted.Items.Add(dt);
this.messagegeted.Items.Add(received);
}//MessageBox.Show("文本框修改成功!");
sr.Close();
mystream.Close();
mytcp.Close();//MessageBox.Show("流关闭,连接关闭!");
}
}
5.连接指定IP地址,并且进行数据传输
连接指定IP
private void button2_Click(object sender, EventArgs e)
{
IPAddress myip = IPAddress.Parse(this.localip.Text.ToString());
IPAddress toip = IPAddress.Parse(this.scanedip.Text.ToString());
TcpClient mytcp = new TcpClient();
try
{
mytcp.Connect(toip, 51888);
}
catch (SocketException)
{
MessageBox.Show("该IP不存在!");
}
this.connectinfo.Items.Add("正在连接IP:");
this.connectinfo.Items.Add(toip);
if (mytcp.Connected == true)
{
this.connectinfo.Items.Add("连接成功!");
this.send.Enabled = true;
mytcp.Close();
}
else
{
this.connectinfo.Items.Add("连接失败!");
this.send.Enabled = false;
}
}
运行截图:
数据传输
private void send_Click(object sender, EventArgs e)
{
DateTime dt = new DateTime();
dt = DateTime.Now;
IPAddress myip = IPAddress.Parse(this.localip.Text.ToString());
IPAddress toip = IPAddress.Parse(this.scanedip.Text.ToString());
TcpClient mytcp = new TcpClient();
mytcp.Connect(toip,51888);//MessageBox.Show("连接建立!");
NetworkStream mystream = mytcp.GetStream();//数据流建立
string message1 = this.sendmessage.Text;
string message2 = this.localip.Text;
string message3 = message1 + " 本条消息来自于:" + message2;
string message4 = "你悄悄的对" + this.scanedip.Text + "说:" + message1;
this.messagegeted.Items.Add(dt);
this.messagegeted.Items.Add(message4);
byte[] sendmessage1 = System.Text.Encoding.UTF8.GetBytes(message3);
mystream.Write(sendmessage1,0,sendmessage1.Length);
mystream.Close();//关闭数据流
mytcp.Close();//关闭连接
this.sendmessage.Clear();//MessageBox.Show("消息发送成功!");
}
运行截图:
四.课程设计过程总结
1.程序总结
程序实现的功能比较简单,只有搜索IP和点对点聊天,其中搜索IP速度很慢,大概要用3秒左右才能搜索一个IP,暂时还没有解决这个问题,总体上达到了课程设计的目标,要求的功能基本都实现了。在后续的功能增强中,会逐步添加群聊还有添加好友的功能,登录界面也要用数据库进行管理,依靠每个人的数据库数据有不同的登录界面和好友。
2.遇到的问题和解决过程
遇到的问题主要是两个,一个是C/S模式都是要一个客户端一个服务端,如何让他们在一个程序中实现;一个是对TCPCLIENT的使用不太熟悉,之前没有用到过。对于TCPCLIENT的学习是自己找资料还有在网上看实例学会的,当时和SOCKET有点弄混了,所以在刚开始的时候出了点小问题,随着对tcpclient的理解的加深问题就解决了。另外一个问题是用线程来解决的,这个方法是参考了网上的高手给的办法,但是用线程是不能更改主线程的控件的,还要加上一句类似声明的代码,这一句代码看似简单,实际上我找到代码并且测试成功用了将近一个小时的时间。在发现问题,解决问题的过程中,我的知识储备也是愈加的丰富,在和同学们的交流中也学习到了很多知识和很多很好的想法。
在这里对191072班的刘锦权同学提出特别感谢,他教给我线程和事件的使用方法。
3.课程设计感想
通过几天紧张有序的忙碌,网络课程设计程序终于出炉了。基于我们之前对TCP的学习和理解,加上在自己买的资料中进行学习,在程序中应用TCP连接还是不太难的。TCP强大的功能和使之实现的简洁的代码给我留下了很深刻的印象,在以后的学习生活中还要进一步进行学习。这一次网络课程设计深化了我对TCP的理解,也对经常要使用的C/S模式有了一定的了解,锻炼了C++的编程动手能力,有很强的成就感。TCP作为连接控件应用非常广泛,前景非常好,我会以这次课程设计为契机,进一步对TCP知识进行学习和发掘。对我而言,知识上的收获重要,精神上的丰收更加可喜。让我知道了学无止境的道理,这次课程设计必将成为我人生旅途上一个非常美好的回忆!
五.附录
日志:
第一天:题目解读,基本思路。通过对课设题目的理解,用c#来做界面会好看一些,控件比较好用, tcp连接来做网络的连接和数据传输,这个程序使用的是传统的C/S模式,所以要写两个程序,服务端不断扫描端口,客户端连接并传输,争取可以用一个程序来完成两个程序的任务。今天主要写了获取本机ip和扫描指定区域ip。
第二天:写基本功能。学习tcpclient的一系列操作后,写出网络连接和数据流,主要实现连接和对单人数据传输。
第三天:测试连接,写界面,增加其他的功能。测试连接可以正常传输信息,主要功能已经实现了,把连接的IP写到界面上变成可更改的数据,在界面上添加控件显示连接信息和聊天信息,搜索IP后对控件数据进行添加,可以显示可以搜索到的IP,增加搜索局域网功能。
第四天:更正逻辑错误,在不同机器上测试程序,补写程序注释。更正了一些释放连接和数据的小错误,在宿舍局域网内测试程序通过,可以正常实现所有功能。然后给程序重要部分写上注释和自己的理解,程序完成!
源程序:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.IO;
using System.Drawing;
namespace 点对点聊天
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void getlanip_Click(object sender, EventArgs e)
{
string hostname1 = Dns.GetHostName();
IPHostEntry myentry = Dns.GetHostByName(hostname1);
IPAddress myaddress = new IPAddress(myentry.AddressList[0].Address);
string myip = myaddress.ToString();
int ipdot = myip.LastIndexOf('.');
myip = myip.Substring(0,ipdot+1);
string aa = "0";
string bb = "255";
string startip = myip + aa;
string endip = myip + bb;
this.ipstart.Text = startip;
this.ipend.Text = endip;
}
private void button1_Click(object sender, EventArgs e)
{
string ipcur = this.ipstart.Text;
int ipdot = ipcur.LastIndexOf('.');
string ippre = ipcur.Substring(0,ipdot+1);
for (int i = 0; i <= 3;i++ )
{
MessageBox.Show("开始搜索");
string scanip = ippre + i.ToString();
IPAddress myscanip = IPAddress.Parse(scanip);
IPHostEntry myscanhost = null;
try
{
myscanhost = Dns.GetHostByAddress(myscanip);
}
catch
{
continue;
}
if (myscanhost.HostName != null)
{
MessageBox.Show("搜索到一个结果");
this.ipbox.Items.Add("可用IP:");
this.ipbox.Items.Add(scanip);
this.ipbox.Items.Add("此IP的主机名:");
this.ipbox.Items.Add(myscanhost.HostName);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
string hostname1 = Dns.GetHostName();
IPHostEntry myentry = Dns.GetHostByName(hostname1);
IPAddress myaddress = new IPAddress(myentry.AddressList[0].Address);
string myip = myaddress.ToString();
this.localip.Text = myip;
this.send.Enabled = false;
Control.CheckForIllegalCrossThreadCalls = false;
Thread server = new Thread(new ThreadStart(serverfuntion));
server.IsBackground = true;
server.Start();
}
private void serverfuntion()
{
DateTime dt = new DateTime();
dt = DateTime.Now;
if (this.scanedip.Text != null)
{
TcpListener mylis = new TcpListener(IPAddress.Any, 51888);
mylis.Start();
while (true)
{
TcpClient mytcp = new TcpClient();
mytcp = mylis.AcceptTcpClient();
// MessageBox.Show("连接建立成功!");
NetworkStream mystream = mytcp.GetStream();
StreamReader sr = new StreamReader(mystream);
// MessageBox.Show("流建立成功!");
string received = "";
received = sr.ReadToEnd();
// MessageBox.Show("消息接受成功!");
if (received != null)
{
this.messagegeted.Items.Add(dt);
this.messagegeted.Items.Add(received);
}
//MessageBox.Show("文本框修改成功!");
sr.Close();
mystream.Close();
mytcp.Close();
//MessageBox.Show("流关闭,连接关闭!");
}
}
private void button2_Click(object sender, EventArgs e)
{
IPAddress myip = IPAddress.Parse(this.localip.Text.ToString());
IPAddress toip = IPAddress.Parse(this.scanedip.Text.ToString());
TcpClient mytcp = new TcpClient();
try
{
mytcp.Connect(toip, 51888);
}
catch (SocketException)
{
MessageBox.Show("该IP不存在!");
}
this.connectinfo.Items.Add("正在连接IP:");
this.connectinfo.Items.Add(toip);
if (mytcp.Connected == true)
{
this.connectinfo.Items.Add("连接成功!");
this.send.Enabled = true;
mytcp.Close();
}
else
{
this.connectinfo.Items.Add("连接失败!");
this.send.Enabled = false;
}
}
private void send_Click(object sender, EventArgs e)
{
DateTime dt = new DateTime();
dt = DateTime.Now;
IPAddress myip = IPAddress.Parse(this.localip.Text.ToString());
IPAddress toip = IPAddress.Parse(this.scanedip.Text.ToString());
TcpClient mytcp = new TcpClient();
mytcp.Connect(toip,51888);//MessageBox.Show("连接建立!");
NetworkStream mystream = mytcp.GetStream();//数据流建立
string message1 = this.sendmessage.Text;
string message2 = this.localip.Text;
string message3 = message1 + " 本条消息来自于:" + message2;
string message4 = "你悄悄的对" + this.scanedip.Text + "说:" + message1;
this.messagegeted.Items.Add(dt);
this.messagegeted.Items.Add(message4);
byte[] sendmessage1 = System.Text.Encoding.UTF8.GetBytes(message3);
mystream.Write(sendmessage1,0,sendmessage1.Length);
mystream.Close();//关闭数据流
mytcp.Close();//关闭连接
this.sendmessage.Clear();//MessageBox.Show("消息发送成功!");
}
}
}
