Server和Client是一对好朋友,有一天Client想知道知道现在几点了就给Server打电话(emmmm就是想他了的意思)
Client把他的手机卡clientfd插到手机卡槽里,拨出了Server的手机号(ip+port):
-
//连接
-
Socket clientfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
clientfd .Connect(
"192.168.196.157",
2000);
但是Server积极拒绝了Client,可能Server没有开机。
Server终于开机了,他在等电话,除此之外什么都不想做(Accpet()是堵塞方法,接收客户端的连接,返回一个连接上的Socket对象,才继续往下执行):
-
//监听套接字
-
Socket listenfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
//绑定ip和port
-
IPAddress ipadr = IPAddress.Parse(
"192.168.196.157");
-
IPEndPoint ipep =
new IPEndPoint(ipadr,
2000);
-
listenfd.Bind(ipep);
-
//监听,0表示不限制连接个数
-
listenfd.Listen(
0);
-
//等待连接
-
Socket clientfd = listenfd.Accept();
开心的是,Client又试着给Server打电话,这次接通了。然后Client问现在几点了:
-
//发送数据
-
sendstr =
"现在几点了" +
'\r';
-
byte[] sendbuff = System.Text.Encoding.Default.GetBytes(sendstr);
-
clientfd.Send(sendbuff);
Server听完了Client的问题后,看了看时间告诉了Client:
-
//接收数据
-
int count = clientfd.Receive(readbuff);
-
readstr = System.Text.Encoding.Default.GetString(readbuff,
0, count);
-
Console.WriteLine(
"Client::"+readstr);
-
-
//反馈
-
sendstr =
"Server:现在是 "+System.DateTime.Now.ToShortTimeString();
-
Console.WriteLine(sendstr);
-
sendbuff = System.Text.Encoding.Default.GetBytes(sendstr);
-
clientfd.Send(sendbuff);
。。。。。正经分割。。。。。。。。
Server端:
-
using System;
-
using System.Collections.Generic;
-
using System.Linq;
-
using System.Net;
-
using System.Net.Sockets;
-
using System.Text;
-
using System.Threading.Tasks;
-
-
namespace
SyncServer
-
{
-
class
Program
-
{
-
static Socket listenfd;
-
static Socket toclientfd;
-
static
byte[] readbuff =
new
byte[
1024];
-
static
byte[] sendbuff =
new
byte[
1024];
-
static
int count;
-
static String readstr =
"";
-
static String sendstr =
"";
-
-
static void Main(string[] args)
-
{
-
//套接字
-
listenfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
//绑定
-
IPAddress ipadr = IPAddress.Parse(
"192.168.196.157");
-
IPEndPoint ipep =
new IPEndPoint(ipadr,
2000);
-
listenfd.Bind(ipep);
-
//监听
-
listenfd.Listen(
0);
-
Console.WriteLine(
"Server已开机(服务器启动成功)");
-
toclientfd = listenfd.Accept();
-
Console.WriteLine(
"接了Client的电话(服务器同意连接)");
-
while (
true)
-
{
-
count = toclientfd.Receive(readbuff);
-
readstr = System.Text.Encoding.Default.GetString(readbuff,
0, count);
-
Console.WriteLine(readstr);
-
sendstr =
"Server:现在是 "+System.DateTime.Now.ToShortTimeString();
-
Console.WriteLine(sendstr);
-
sendbuff = System.Text.Encoding.Default.GetBytes(sendstr);
-
toclientfd.Send(sendbuff);
-
}
-
-
}
-
}
-
}
Client端:
-
using System;
-
using System.Net.Sockets;
-
using System.Windows.Forms;
-
-
namespace
SyncClient
-
{
-
public
partial
class
Form1 :
Form
-
{
-
public Form1()
-
{
-
InitializeComponent();
-
}
-
-
string sendstr =
"";
-
string readstr =
"";
-
Socket socket;
-
byte[] readBuff =
new
byte[
1024];
-
-
private void Conn_btn_Click(object sender, EventArgs e)
-
{
-
socket =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
socket.Connect(
"192.168.196.157",
2000);
-
Dialog.Items.Add(
"Server接电话啦(服务器已连接)");
-
}
-
-
private void Send_btn_Click(object sender, EventArgs e)
-
{
-
sendstr =
"Client:" + textBox1.Text +
'\r';
-
byte[] sendbuff = System.Text.Encoding.Default.GetBytes(sendstr);
-
socket.Send(sendbuff);
-
Dialog.Items.Add( sendstr);
-
int count = socket.Receive(readBuff);
-
readstr = System.Text.Encoding.Default.GetString(readBuff,
0, count);
-
Dialog.Items.Add(readstr);
-
}
-
}
-
}
。。。。。正经分割。。。。。。。。
但是,Client发现有时候Server不接电话,自己只能一直打一直打(Connect()是阻塞方法),有时候自己说错了,赶快重新说一次,但是Server愣住了没有反应(Receive()是阻塞方法),有时候别人跟Server聊着天,自己就只能等他们聊完,Server也不喜欢一直守着电话(Accept()是阻塞方法)、等别人说话回复别人卡死(Send()是阻塞方法)的感觉,于是他们换了一种打电话的方式。
Server开好机后,做些别的时间,没事看两眼有没有电话(BeginAccept(....)非阻塞方法,异步):
-
//套接字
-
Socket listenfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
//绑定
-
IPAddress ipadr = IPAddress.Parse(
"192.168.196.157");
-
IPEndPoint ipep =
new IPEndPoint(ipadr,
2000);
-
listenfd.Bind(ipep);
-
//监听
-
listenfd.Listen(
0);
-
listenfd.BeginAccept(AcceptCallback, listenfd);
-
-
-
public void AcceptCallback(IAsyncResult ar)
-
{
-
try
-
{
-
-
Socket listenfd = (Socket)ar.AsyncState;
-
clientfd= listenfd.EndAccept(ar);
-
-
}
catch (Exception e) {
-
Console.WriteLine(e.ToString());
-
}
-
}
Client也是,拨出(BeginConnect(...)非阻塞方法,异步)号码后把手边的东西清一清:
-
private void Conn_btn_Click(object sender, EventArgs e)
-
{
-
clientfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
//连接同一局域网
-
clientfd.BeginConnect(
"192.168.196.157",
2000,ConnectCallback, clientfd);
-
}
-
-
public void ConnectCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket socket = (Socket)ar.AsyncState;
-
socket.EndConnect(ar);
-
-
}
catch(Exception e)
-
{
-
Console.WriteLine(
"Socket Connect fail:" + e.ToString());
-
}
-
}
Server接了电话后,他们开始聊天了,不用等着对方说话,有声音的话就去听,没声音的时候可以做点别的。
-
clientfd.BeginReceive(readBuff,
0,
1024,
0, ReceiveCallback, clientfd);
-
clientfd.BeginSend(sendBuff)
-
-
-
public void ReceiveCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket socket = (Socket)ar.AsyncState;
-
int count = socket.EndReceive(ar);
-
-
string readstr = System.Text.Encoding.Default.GetString(readBuff,
0, count);
-
socket.BeginReceive(readBuff,
0,
1024,
0, ReceiveCallback, socket);
-
-
}
catch (Exception e)
-
{
-
Console.WriteLine(
"Socket Reveive fail: " + e.ToString());
-
}
-
}
-
-
-
public void SendCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket socket = (Socket)ar.AsyncState;
-
socket.EndSend(ar);
-
}
catch(Exception e)
-
{
-
Console.WriteLine(e.ToString());
-
}
-
}
。。。。。正经分割。。。。。。。。
Server端:
-
using System;
-
using System.Collections.Generic;
-
using System.ComponentModel;
-
using System.Data;
-
using System.Drawing;
-
using System.Linq;
-
using System.Net;
-
using System.Net.Sockets;
-
using System.Text;
-
using System.Threading.Tasks;
-
using System.Windows.Forms;
-
-
namespace
EchoServer
-
{
-
public
partial
class
ServerWin :
Form
-
{
-
public ServerWin()
-
{
-
InitializeComponent();
-
}
-
-
Socket listenfd;
-
Socket clientfd;
-
byte[] readBuff =
new
byte[
1024];
-
byte[] sendbuff =
new
byte[
1024];
-
-
private void Listen_btn_Click(object sender, EventArgs e)
-
{
-
//套接字
-
listenfd =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
//绑定
-
IPAddress ipadr = IPAddress.Parse(
"192.168.196.157");
-
IPEndPoint ipep =
new IPEndPoint(ipadr,
2000);
-
listenfd.Bind(ipep);
-
//监听
-
listenfd.Listen(
0);
-
Dialog.Items.Add(
"Server已开机(服务器启动成功)");
-
listenfd.BeginAccept(AcceptCallback, listenfd);
-
-
}
-
-
private void Send_btn_Click(object sender, EventArgs e)
-
{
-
byte[] sendbuff = System.Text.Encoding.Default.GetBytes(textBox1.Text);
-
clientfd.BeginSend(sendbuff,
0,sendbuff.Length,
0,SendCallback, clientfd);
-
SetProgressDelegate setprogress =
new SetProgressDelegate(SetProgress);
-
this.Invoke(setprogress,
new
object[] {
"Server:"+ textBox1.Text,
"" });
-
}
-
-
-
-
public delegate void SetProgressDelegate(String str,String name);
-
-
public void SetProgress(String str, String name)
-
{
-
Dialog.Items.Add(str);
-
if(name!=
null)
-
Online.Items.Add(name);
-
}
-
-
public void AcceptCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket listenfd = (Socket)ar.AsyncState;
-
clientfd= listenfd.EndAccept(ar);
-
-
// Dialog.Items.Add("Client上线啦");
-
SetProgressDelegate setprogress =
new SetProgressDelegate(SetProgress);
-
this.Invoke(setprogress,
new
object[] {
"Client上线啦",
"Client" });
-
-
sendbuff = System.Text.Encoding.Default.GetBytes(
"接了Client的电话(服务器同意连接)");
-
clientfd.Send(sendbuff);
-
clientfd.BeginReceive(readBuff,
0,
1024,
0, ReceiveCallback, clientfd);
-
-
}
-
catch (Exception e)
-
{
-
Console.WriteLine(e.ToString());
-
}
-
}
-
-
-
public void ReceiveCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket socket = (Socket)ar.AsyncState;
-
int count = socket.EndReceive(ar);
-
-
string readstr = System.Text.Encoding.Default.GetString(readBuff,
0, count);
-
//Dialog.Items.Add(name+":"+ readstr);
-
SetProgressDelegate setprogress =
new SetProgressDelegate(SetProgress);
-
this.Invoke(setprogress,
new
object[] {
"Client:" + readstr,
"" });
-
-
socket.BeginReceive(readBuff,
0,
1024,
0, ReceiveCallback, socket);
-
-
}
-
catch (Exception e)
-
{
-
Console.WriteLine(
"Socket Reveive fail: " + e.ToString());
-
}
-
}
-
-
public void SendCallback(IAsyncResult ar)
-
{
-
try
-
{
-
Socket socket = (Socket)ar.AsyncState;
-
socket.EndSend(ar);
-
}
catch(Exception e)
-
{
-
Console.WriteLine(e.ToString());
-
}
-
}
-
-
}
-
}
Client端:
-
using System;
-
using System.Net.Sockets;
-
using System.Windows.Forms;
-
-
namespace
SyncClient
-
{
-
public
partial
class
Form1 :
Form
-
{
-
public Form1()
-
{
-
InitializeComponent();
-
}
-
-
string sendstr =
"";
-
string readstr =
"";
-
Socket socket;
-
byte[] readBuff =
new
byte[
1024];
-
-
private void Conn_btn_Click(object sender, EventArgs e)
-
{
-
socket =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
socket.Connect(
"192.168.196.157",
2000);
-
Dialog.Items.Add(
"Server接电话啦(服务器已连接)");
-
}
-
-
private void Send_btn_Click(object sender, EventArgs e)
-
{
-
sendstr =
"Client:" + textBox1.Text +
'\r';
-
byte[] sendbuff = System.Text.Encoding.Default.GetBytes(sendstr);
-
socket.Send(sendbuff);
-
Dialog.Items.Add( sendstr);
-
int count = socket.Receive(readBuff);
-
readstr = System.Text.Encoding.Default.GetString(readBuff,
0, count);
-
Dialog.Items.Add(readstr);
-
}
-
}
-
}
。。。。。正经分割。。。。。。。。
现在他们可以愉快的聊天啦。
。。。。。。。。。。。。。。。。。。。。。正经强分割。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
怎么连接的:
Server端的重点(同步的方法时):
1)创建服务端的套接字, 实例初始化 System.Net.Sockets.Socket 类使用指定的地址族、 套接字类型和协议。其中AddressFamily的InterNetwork指ipv4地址,SocketType.stream指定字节流,ProtocolType.Tcp指定使用TCP协议传输。
Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2)Bind绑定地址ip和端口port
-
//绑定
-
IPAddress ipadr = IPAddress.Parse(
"192.168.196.157");
-
IPEndPoint ipep =
new IPEndPoint(ipadr,
2000);
-
listenfd.Bind(ipep);
3)Listen开启监听,socket.Listen(backlog),backlog限定队列中最多容纳等待接收的连接数,0表示不限制
-
//监听
-
listenfd.Listen(
0);
4)同意连接Accept(),属于阻塞方法,当没有客户端的连接申请时,服务端阻塞在这里,直到接收到客户的连接,返回一个客户端的socket对象。
Socket clientfd= listenfd.Accept();
5)可以看出,服务端有两种套接字,一个监听套接字,用来监听绑定的地址和端口上时候有客户端的申请连接,一个对应客户端的套接字,用于接收和发送指定对象数据。
Client端重点(同步的方法时):
1)创建客户端套接字,同服务端
Socket clientfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2)申请连接,Connect(ip,port),属于阻塞方法,会一直卡住等待服务器接收,超时或拒绝
clientfd.Connect("192.168.196.157", 2000);
3)发送数据Send,接收数据Receive,都属于阻塞方法
-
clientfd.Send(sendBuff)
-
clientfd.Receive(readBuff)
同步->异步
同步方法 | 异步方法 | |
---|---|---|
Accept |
BeginAccept 开始一个异步操作来接收连接请求 |
EndAccept 异步连接 |
Connect | BeginConnect 开始一个异步操作来申请连接 |
EndConnect 结束挂起的异步连接请求 |
Receive | BeginReceive 开始一个异步操作来接收数据 |
EndReceive 将数据异步发送到连接套接字 |
Send | BeginSend 开始一个异步操作来发送数据 |
EndSend 结束挂起的异步发送 |
异步的核心接口:IAsyncResult
-
#region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
-
#endregion
-
-
using System.Runtime.InteropServices;
-
using System.Threading;
-
-
namespace
System
-
{
-
//
-
// 摘要:
-
// 表示异步操作的状态。
-
[
ComVisible(true)]
-
public
interface
IAsyncResult
-
{
-
//
-
// 摘要:
-
// 获取一个值,该值指示异步操作是否已完成。
-
//
-
// 返回结果:
-
// 如果操作已完成,则为 true;否则为 false。
-
bool IsCompleted {
get; }
-
//
-
// 摘要:
-
// 获取用于等待异步操作完成的 System.Threading.WaitHandle。
-
//
-
// 返回结果:
-
// 用于等待异步操作完成的 System.Threading.WaitHandle。
-
WaitHandle AsyncWaitHandle {
get; }
-
//
-
// 摘要:
-
// 获取一个用户定义的对象,该对象限定或包含有关异步操作的信息。
-
//
-
// 返回结果:
-
// 一个用户定义的对象,限定或包含有关异步操作的信息。
-
object AsyncState {
get; }
-
//
-
// 摘要:
-
// 获取一个值,该值指示异步操作是否同步完成。
-
//
-
// 返回结果:
-
// 如果异步操作同步完成,则为 true;否则为 false。
-
bool CompletedSynchronously {
get; }
-
}
-
}
实现IAsyncResult的回调方法是多线程的方法,以达到异步的目的。IAsyncResult中的AsyncState对象就是当前线程中操作的客户/服务端套接字。
委托机制 : delegate
回调方法中不能进行UI操作,上述异步例程中使用委托的方式更新UI,将异步接收的数据显示在对话框中,具体不作描述。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
写在最后:花花冲鸭!
转载:https://blog.csdn.net/weixin_38247439/article/details/88529909