同步socket一般有利用socket库直接,就可以写出tcp或udp的套接字
socketserver提供的线程或进程方式的socket
利用python 3.5+的asyncio协议,封装一个协程的socket server ,普通的socket客户也可以连接。
服务器端
为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
构造报头信息
服务端
客户端
粘包,分包都tcp
tcp为什么会有粘包分包这些情况:
1.服务端处理不过来
2.客户端采用优化纳格尔算法,达到一定字节才发
怎么处理:
1. 客,服双方确定包头规范,根据包头的信息取包长度
2. 客户端发送带上标记位,如\n, 服务端根据标记取包
服务器端
客户端
服务器端
客户端
服务器端
客户端
封装了socket,而且解决了Io阻塞问题
服务端
客户端
客户端
参考:
http://www.cnblogs.com/jokerbj/p/7422349.html
http://xiaorui.cc/2016/03/08/%E8%A7%A3%E5%86%B3golang%E5%BC%80%E5%8F%91socket%E6%9C%8D%E5%8A%A1%E6%97%B6%E7%B2%98%E5%8C%85%E5%8D%8A%E5%8C%85bug/
http://xiaorui.cc/2016/04/15/%E6%89%93%E9%80%A0mvc%E6%A1%86%E6%9E%B6%E4%B9%8Bsocket%E8%8E%B7%E5%8F%96http%E7%B2%98%E5%8C%85%E9%97%AE%E9%A2%98/
https://www.jianshu.com/p/065c53cab328
https://mozillazg.com/2017/08/python-asyncio-note-io-protocol.html#hidid3
我以前写过类似的socket通信,虽然你用的方法和我的不太一样,但我还是感觉有一些问题接受消息的时候,你用的是while(true)循环,当第一次将消息接受后,缓冲区就为空了,我想你再用循环去接收应该会出问题。
我记得有个poll方法,具体什么用途忘记了(很久没写代码了)你在循环里面加个if (clientsocket.Poll(1000, SelectMode.SelectRead))判断语句“clientsocket为你需要接收消息的socket”看看能不能解决,或者就用异步也可以,我可以发一下我以前的代码你参考下:
using System
using System.Collections.Generic
using System.ComponentModel
using System.Data
using System.Drawing
using System.Text
using System.Windows.Forms
using System.Net
using System.Net.Sockets
using System.Threading
namespace test4_2
{
public partial class Form1 : Form
{
Socket connectSocket
//Socket client
byte[] bytes = new byte[1024]
delegate void listboxDel(string s)
listboxDel listboxdel
public Form1()
{
InitializeComponent()
textBoxContent.Focus()
listboxdel = new listboxDel(listbox)
//为连接指派线程
Thread threadConnect = new Thread(new ThreadStart(Connect))
threadConnect.Start()
}
public void listbox(string str)
{
listBox1.Items.Add(str)
listBox1.SelectedIndex = listBox1.Items.Count - 1
listBox1.ClearSelected()
}
//连接方法
public void Connect()
{
try
{
//建立连接socket
connectSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp)
//开始异步连接
connectSocket.BeginConnect(IPAddress.Parse("172.16.94.152"),
82,
new AsyncCallback(ConnectCallback), //定义回调函数代理
connectSocket) //传递给回调函数的状态
}
catch (Exception e)
{
MessageBox.Show(e.Message)
}
}
//连接方法的回调函数
private void ConnectCallback(IAsyncResult ar)
{
try
{
//从传递的状态中获取套接字,创建一个客户端套接字
Socket client = (Socket)ar.AsyncState
//完成挂起的连接操作
client.EndConnect(ar)
listBox1.Invoke(listboxdel, "连接服务器成功,可以开始通话!")
client.BeginReceive(bytes, 0, 1000, 0, new AsyncCallback(receivecallback), client)
}
catch (Exception e)
{
Console.WriteLine(e.ToString())
}
}
public void receivecallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState
int length = client.EndReceive(ar)
listBox1.Invoke(listboxdel, Encoding.UTF8.GetString(bytes, 0, length))
client.BeginReceive(bytes, 0, 1000, 0, new AsyncCallback(receivecallback), client)
}
catch
{
}
}
//发送方法
private void Send(String data)
{
//使用ASCII转换字符串为字节序列
byte[] byteData = Encoding.UTF8.GetBytes(data) //将字符串转换成字节序列
//开始向远端设备发送数据
connectSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(SendCallback), connectSocket)
}
//发送方法的回调函数
private void SendCallback(IAsyncResult ar)
{
try
{
//从传递的状态中获取套接字,创建一个客户端套接字
Socket client = (Socket)ar.AsyncState
//结束异步数据传输操作,返回传输的字节数
int bytesSent = client.EndSend(ar)
listBox1.Invoke(listboxdel, textBoxUser.Text +":"+ textBoxContent.Text)
}
catch (Exception e)
{
MessageBox.Show(e.ToString())
}
}
private void buttonSend_Click(object sender, EventArgs e)
{
Send(textBoxUser.Text+":"+textBoxContent.Text)
}
}
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)