要求:
1.可以完成一对一的通信;
2.实现服务端对客户端一对多的选择发送;
3.可以实现服务端的群发功能;
4.可以实现客户端文件的发送;

要点:
服务器端:
第一步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第二步:建立一个Socket对像;
第三步:用socket对像的Bind()方法绑定EndPoint;
第四步:用socket对像的Listen()方法开始监听;
第五步:接受到客户端的连接,用socket对像的Accept()方法创建新的socket对像用于和请求的客户端进行通信;
第六步:通信结束后一定记得关闭socket;

客户端:
第一步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第二步:建立一个Socket对像;
第三步:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求;
第四步:如果连接成功,就用socket对像的Send()方法向服务器发送信息;
第五步:用socket对像的Receive()方法接受服务器发来的信息 ;
第六步:通信结束后一定记得关闭socket;

服务端代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO; namespace Socket_ServerAndClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
} Thread threadWatch = null;
Socket socketWatch = null; /// <summary>
/// 创建服务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(address,int.Parse(txtPort.Text.Trim()));
socketWatch.Bind(endpoint);
socketWatch.Listen(10);
threadWatch = new Thread(WatchConnection);
threadWatch.IsBackground = true;
threadWatch.Start();
ShowMsg("服务器监听成功......");
} //Socket sokConnection = null;
Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>(); /// <summary>
/// 监听客户端的请求方法
/// </summary>
/// <param name="obj"></param>
private void WatchConnection(object obj)
{
while (true)
{
// 负责通信的套接字
Socket sokConnection = socketWatch.Accept();
lb_Online.Items.Add(sokConnection.RemoteEndPoint.ToString());
dict.Add(sokConnection.RemoteEndPoint.ToString(),sokConnection); //创建通信线程
ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);// 委托
Thread thr = new Thread(pts);
thr.IsBackground = true;
thr.Start(sokConnection);
dictThread.Add(sokConnection.RemoteEndPoint.ToString(),thr); ShowMsg("客户端连接成功......"+sokConnection.RemoteEndPoint.ToString());
}
} /// <summary>
/// 服务端负责监听客户端发送消息的方法
/// </summary>
void RecMsg(object socketClient)
{
Socket socketClients = socketClient as Socket;
while (true)
{
byte[] arrMsgRec = new byte[1024 * 1024 * 2]; int length = -1;
try
{
length = socketClients.Receive(arrMsgRec);
}
catch (SocketException ex)
{
ShowMsg("异常:" + ex.Message);
// 从 通信套接字 集合中删除被中断连接的套接字对象
dict.Remove(socketClients.RemoteEndPoint.ToString());
// 从 通信线程 集合中删除被中断连接的套接字对象
dictThread.Remove(socketClients.RemoteEndPoint.ToString());
// 从 列表 中移除 IP&Port
lb_Online.Items.Remove(socketClients.RemoteEndPoint.ToString());
break;
}
catch (Exception ex)
{
ShowMsg("异常:" + ex.Message);
break;
}
// 判断第一个发送过来的数据如果是1,则代表发送过来的是文本数据
if (arrMsgRec[0] == 0)
{
string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
ShowMsg(strMsgRec);
}
// 若是1则发送过来的是文件数据(文档,图片,视频等。。。)
else if(arrMsgRec[0] == 1)
{
// 保存文件选择框对象
SaveFileDialog sfd = new SaveFileDialog();
// 选择文件路径
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
// 获得保存文件的路径
string fileSavePath = sfd.FileName;
// 创建文件流,然后让文件流根据路径创建一个文件
using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
{
fs.Write(arrMsgRec, 1, length - 1);
ShowMsg("文件保存成功:"+fileSavePath);
}
}
}
}
} private void ShowMsg(string p)
{
txtMsg.AppendText(p+"\r\n");
} /// <summary>
/// 发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Send_Click_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(lb_Online.Text))
{
MessageBox.Show("请选择发送的好友!!!");
}
else
{
string strMsg = tb_Msg_Send.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
string strClientKey = lb_Online.Text;
try
{
dict[strClientKey].Send(arrMsg);
ShowMsg("发送了数据出去:"+strMsg);
}
catch (SocketException ex)
{
ShowMsg("发送时异常:" + ex.Message);
}
catch(Exception ex)
{
ShowMsg("发送时异常:" + ex.Message);
}
// sokConnection.Send(arrMsg);
ShowMsg("发送了数据出去:"+strMsg);
}
} /// <summary>
/// 群发消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SendToAll_Click(object sender, EventArgs e)
{
string strMsg = txtMsg.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
foreach (Socket item in dict.Values)
{
item.Send(arrMsg);
}
ShowMsg("群发完毕!!!:)");
}
}
}

  

客户端代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO; namespace Socket_Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
} Thread threadRec = null;
Socket socketClient = null; private void btn_Connect_Click(object sender, EventArgs e)
{
IPAddress address = IPAddress.Parse(tb_IP.Text.Trim());
IPEndPoint endport = new IPEndPoint(address,int.Parse(tb_Port.Text.Trim()));
socketClient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
socketClient.Connect(endport); threadRec = new Thread(RecMsg);
threadRec.IsBackground = true;
threadRec.Start();
} void RecMsg()
{
while (true)
{
byte[] arrMsgRec = new byte[1024*1024*2];
int length = socketClient.Receive(arrMsgRec);
string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length);
ShowMsg(strMsgRec);
}
} private void ShowMsg(string msg)
{
tb_Msg.AppendText(msg+"\r\n");
} private void btnSendMsg_Click(object sender, EventArgs e)
{
string strMsg = txtMsgSend.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrMsgSend = new byte[arrMsg.Length];
// 添加标识位,0代表发送的是文字
arrMsgSend[0] = 0;
Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length);
socketClient.Send(arrMsg);
ShowMsg("I say:"+strMsg);
} /// <summary>
/// 选择文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btChoseFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtFilePath.Text = ofd.FileName;
}
} /// <summary>
/// 发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btSendFile_Click(object sender, EventArgs e)
{
using (FileStream fs = new FileStream())
{
byte[] arrFile = new byte[1024*1024*2];
int length = fs.Read(arrFile, 0, arrFile.Length);
byte[] arrFileSend = new byte[length+1];
arrFileSend[0] = 1;// 代表文件数据
// 将数组 arrFile 里的数据从第零个数据拷贝到 数组 arrFileSend 里面,从第1个开始,拷贝length个数据
Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
socketClient.Send(arrFileSend);
}
}
}
}

程序运行截图:

  

(C#:Socket)简单的服务端与客户端通信。的更多相关文章

  1. Netty 学习(二):服务端与客户端通信

    Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...

  2. C#Winform窗体实现服务端和客户端通信例子(TCP/IP)

    Winform窗体实现服务端和客户端通信的例子,是参考这个地址 http://www.cnblogs.com/longwu/archive/2011/08/25/2153636.html 进行了一些异 ...

  3. C# 编写WCF简单的服务端与客户端

    http://www.wxzzz.com/1860.html Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Win ...

  4. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

  5. socket创建UDP服务端和客户端

    UDP服务端代码示例: from socket import * #1.创建数据报套接字 sockfd = socket(AF_INET, SOCK_DGRAM) #2.绑定服务端地 sockfd.b ...

  6. socket创建TCP服务端和客户端

    看情况选择相对应的套接字*面向连接的传输--tcp协议--可靠的--流式套接字(SOCK_STREAM)*面向无连接的传输--udp协议--不可靠的--数据报套接字(SOCK_DGRAM) 在liun ...

  7. go --socket通讯(TCP服务端与客户端的实现)

    这篇文章主要使用Go语言实现一个简单的TCP服务器和客户端.服务器和客户端之间的协议是 ECHO, 这个RFC 862定义的一个简单协议.为什么说这个协议很简单呢, 这是因为服务器只需把收到的客户端的 ...

  8. C# Socket简单例子(服务器与客户端通信)

    这个例子只是简单实现了如何使用 Socket 类实现面向连接的通信. 注意:此例子的目的只是为了说明用套接字写程序的大概思路,而不是实际项目中的使用程序.在这个例子中,实际上还有很多问题没有解决,如消 ...

  9. java网络编程-单线程服务端与客户端通信

    该服务器一次只能处理一个客户端请求;p/** * 利用Socket进行简单服务端与客户端连接 * 这是服务端 */public class EchoServer { private ServerSoc ...

随机推荐

  1. 【转】聊聊HTTPS和SSL/TLS协议

    要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识.1. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义2. 大致了解 HTTP 和 TCP 的关系(尤其是“短连接”VS“长连接 ...

  2. CSS 弹性盒子布局

    学习地址:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout

  3. Docker学习小计

    1.自动下载并且创建容器 Now verify that the installation has worked by downloading the ubuntu image and launchi ...

  4. Microsoft Visual 的变态

    Microsoft Visual 里面使用指针 的时候, 声明要放在函数开始的位置,否则报错,真变态啊 刚刚发现,C的变量必须在语块开始声明,后面声明会报错,太不灵活了

  5. 基于 Python 和 Scikit-Learn 的机器学习介绍

    Reference:http://mp.weixin.qq.com/s?src=3&timestamp=1474985436&ver=1&signature=at24GKibw ...

  6. IOS 子视图获取父视图的控制器

    UIResponder* nextResponder = [self.view.superview.superview nextResponder]; if ([nextResponder isKin ...

  7. win8系统换win7系统

    吐槽一下先,win8换win7好费事~第一次弄,不过总算弄好了,记录一下吧. 首先,最坑人的就是,win8没法像win7那样按F1或者别的,直接进入BIOS,也就没法设置U盘引导,据说是由于win8的 ...

  8. Eclipse寻找JVM的机制

    Eclipse寻找JVM的机制 查看当前用了哪个jvm的方法: Help->About Eclipse -> Installation Details ->Configuration ...

  9. Flex timer使用 keydown事件注册到stage

    Flex timer使用 keydown事件注册到stage: <?xml version="1.0" encoding="utf-8"?> < ...

  10. JSP模板文本

    JSP模板文本: http://book.51cto.com/art/200907/136020.htm JSP页面就是带有JSP元素的常规Web页面,它是由JSP模版文本和JSP元素组成的.在一个J ...