Tcp与Ip协议的客户端和服务器编程
本文就TCP和Ip协议的客户端和服务器分别进行编程,实现了客户端和服务端进行通信的功能,服务端对多个客户端进行监听,并能与多个客户端通信。
服务器端代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 服务端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(
object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls =
false;
}
/// <summary>
/// 获取本机IP地址
/// </summary>
/// <returns>返回一个IP</returns>
private string GetIpAddress()
{
string hostName = Dns.GetHostName();
//获取本机名
IPHostEntry localhost = Dns.GetHostByName(hostName);
//方法已过期了,只能得到一个IPV4的地址
IPAddress localaddr = localhost.AddressList[
0];
return localaddr.ToString();
}
private void btnStart_Click(
object sender, EventArgs e)
{
try
{
//当点击开始监听时,在服务器端创建一个负责监听IP地址和端口号的Socket
//IP V4,流式服务,TCP协议
Socket socketWatch =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
//IPAddress.Parse(txtServer.Text);我的理解是获取本机IP
txtServer.Text = GetIpAddress();
//将IP地址给文本
//创建端口号对象
IPEndPoint point =
new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//监听
socketWatch.Bind(point);
ShowMsg("监听成功");
socketWatch.Listen(10);
//一次监听10 人
///创建一个线程来监听,否则没监听时就卡死了
Thread th =
new Thread(Listen);
th.IsBackground =
true;
th.Start(socketWatch);
}
catch { }
}
Dictionary<
string, Socket> dicSock =
new Dictionary<
string, Socket>();
//创建键值对来存放IP和socket
Socket socketSend;
void Listen(
object o)
//必须用object类型 ,因为线程要使用
{
Socket socketWatch = o
as Socket;
//将传递过来的参数转换为Socket类型
while (
true)
{
try
{
//等待客户端的连接 并且创建一个负责通信的Socket
socketSend =
socketWatch.Accept();
//获得远端 IP+端口号:连接成功
ShowMsg(socketSend.RemoteEndPoint.ToString() +
":" +
"连接成功");
dicSock.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//将IP地址添加到下拉列表中
comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString());
Thread th =
new Thread(ReciveMsg);
//在线程中只写方法名,括号和里面的参数不写在这里
th.IsBackground =
true;
//写为后台线程,这样关闭窗口时线程就关闭了,否则关闭不了,会报错
th.Start(socketSend);
}
catch
{ }
}
}
/// <summary>
/// 用来接收客户端发送来的信息,线程来调用他
/// </summary>
/// <param name="o"></param>
void ReciveMsg(
object o)
{
Socket socketSend = o
as Socket;
while (
true)
{
try
{
//连接成功之后,客户端就要给服务端发送数据了
byte[] buffer =
new byte[
1024 *
1024 *
2];
int r = socketSend.Receive(buffer);
//实际接收到的有效字符
if (r ==
0)
{
break;
}
string str = Encoding.UTF8.GetString(buffer,
0, r);
ShowMsg(socketSend.RemoteEndPoint +
":" +
str);
}
catch { }
}
}
/// <summary>
/// 在上面一个文本框中显示信息的方法
/// </summary>
/// <param name="str"></param>
void ShowMsg(
string str)
{
txtLOg.AppendText(str +
"\r\n");
//写AppendText追加,不然会覆盖
}
/// <summary>
/// 服务端给客户端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(
object sender, EventArgs e)
{
try
{
if (comboBox1.Text ==
"")
{
MessageBox.Show("请选中一个客户端地址再发送消息",
"谢谢");
}
string str =
textBox4.Text;
textBox4.Clear();
byte[] buffer =
System.Text.Encoding.UTF8.GetBytes(str);
List<
byte> list =
new List<
byte>
();
list.Add(0);
list.AddRange(buffer);
byte[] newbuffer =
list.ToArray();
string ip =
comboBox1.SelectedItem.ToString();
dicSock[ip].Send(newbuffer);//通过键IP地址找到值socketSend
//socketSend.Send(buffer);
}
catch
{ }
}
private void button2_Click(
object sender, EventArgs e)
{
if (comboBox1.Text ==
"")
{
MessageBox.Show("请选择一个客户端IP地址再选择要发送的文件",
"提示!");
}
else
{
OpenFileDialog ofd =
new OpenFileDialog();
ofd.Title =
"请选择要发送的文件";
ofd.InitialDirectory =
@"C:\Users\Administrator\Desktop";
ofd.Filter =
"所有文件|*.*";
ofd.ShowDialog();
textBox5.Text = ofd.FileName;
//获得选中的一个文件名
}
}
/// <summary>
/// 发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(
object sender, EventArgs e)
{
try
{
//发送文件
string path =
textBox5.Text;
using (FileStream fsRead =
new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buffer =
new byte[
1024 *
1024 *
5];
int r = fsRead.Read(buffer,
0, buffer.Length);
List<
byte> list =
new List<
byte>
();
list.Add(1);
list.AddRange(buffer);
byte[] newbuffer =
list.ToArray();
//int r= fsRead.Read(newbuffer , 0, newbuffer.Length);//实际读取的有效字节
dicSock[comboBox1.SelectedItem.ToString()].Send(newbuffer,
0, r +
1, SocketFlags.None);
}
}
catch { }
}
///让客户端震动
private void button5_Click(
object sender, EventArgs e)
{
try
{
if (comboBox1.Text ==
"")
{
MessageBox.Show("请选择一个客户端IP地址再震动",
"提示!");
}
else
{
byte[] buffer =
new byte[
1];
buffer[0] =
2;
dicSock[comboBox1.SelectedItem.ToString()].Send(buffer);
}
}
catch { }
}
}
}
客户端代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 客户端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socketConnect =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void button1_Click(
object sender, EventArgs e)
{
try
{
//建立负责通讯的Socket
if (textBox1.Text ==
"" || textBox2.Text ==
"")
{
MessageBox.Show("IP地址或者端口号不能为空",
"去你大爷的!");
}
IPAddress ip =
IPAddress.Parse(textBox1.Text);
IPEndPoint point =
new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
socketConnect.Connect(point);
ShowMsg("连接成功");
Thread th =
new Thread(Receive);
th.IsBackground =
true;
th.Start();
}
catch { }
}
void ShowMsg(
string str)
{
textBox3.AppendText(str +
"\r\n");
}
private void button2_Click(
object sender, EventArgs e)
{
try
{
//客户端要给服务器发送消息
string str = textBox4.Text.Trim();
//Trim()就是把所写内容前后空格去除
byte[] buffer = Encoding.UTF8.GetBytes(str);
//System.Text.Encoding.UTF8.GetBytes(str);
socketConnect.Send(buffer);
textBox4.Clear();
}
catch { }
}
///写一个不断接收服务端发过来的消息的方法,创建线程来调用他
void Receive()
{
try
{
while (
true)
//不停的接收
{
byte[] buffer =
new byte[
1024 *
1024 *
3];
int r = socketConnect.Receive(buffer);
//实际接收到的有效字节数
if (r ==
0)
{
break;
}
if (buffer[
0] ==
0)
//接收到文字
{
string str = Encoding.UTF8.GetString(buffer,
1, r -
1);
ShowMsg(socketConnect.RemoteEndPoint +
":" +
str);
}
else if (buffer[
0] ==
1)
{
//接收的是文件
SaveFileDialog ofd =
new SaveFileDialog();
//保存对话框
ofd.Title =
"请选择保存文件的路径";
ofd.InitialDirectory =
@"C:\Users\Administrator\Desktop";
ofd.Filter =
"所有文件|*.*";
ofd.ShowDialog(this);
string path =
ofd.FileName;
using (FileStream fsWrite =
new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(buffer, 1, r -
1);
}
MessageBox.Show("保存成功",
"kao");
}
else if(buffer [
0]==
2)
{
ZD();
}
}
}
catch { }
}
/// <summary>
/// 写个方法来使窗体震动
/// </summary>
void ZD()
{
for (
int i =
0; i <
500; i++
)
{
this.Location =
new Point(
200 ,
200);
this.Location =
new Point(
280 ,
280);
}
}
private void Form1_Load(
object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls =
false;
}
}
}
转载于:https://www.cnblogs.com/xiaoyaohan/p/9755748.html
相关资源:自己写一个tcp 通用服务器