C#SOCKET长连接小数据程序未响应,该如何解决
C#SOCKET长连接小数据程序未响应
最近由于业务的需要,Linux系统嵌入式设备往我做的服务程序发送数据。
速度奇慢,而且还是程序无响应。后来自己用C#写了一个客户端用来测试。已经用了线程池,不知道用法对不对。请大家帮忙看下。
服务端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace consoleSocketServer
{
class Program
{
static int socketCount = 0;
static Socket serverSocket;
static Socket clientSocket;
public static int clientcount = 0;
public int clientnum = 0;
static int listSQL = 0;
static bool asy = true;
public static Int32 portServer = 0;
public static string ipServer = "";
public static Thread threadSocketListen;
public static Thread threadDoWork;
public static Thread threadInsert;
public static int countsql = 0;
static void Main(string[] args)
{
IPAddress ipAddress;
portServer = 4660;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ipAddress = IPAddress.Parse("192.168.33.29");
ipServer = ipAddress.ToString();
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
Console.WriteLine("服务器IP:" + ipServer + " 端口:" + portServer);
serverSocket.Bind(localEndPoint);
serverSocket.Listen(20);
//设置线程池
ThreadPool.SetMaxThreads(4, 4);
//开启新的线程监听
threadSocketListen = new Thread(SocketListen);
threadSocketListen.Start();
Console.WriteLine("服务启动成功");
}
static void SocketListen()
{
while (true)
{
//接受客户端信息
clientSocket = serverSocket.Accept();
//开启处理线程
ThreadPool.QueueUserWorkItem(new WaitCallback(doWork));
//threadDoWork = new Thread(new ThreadStart(doWork));
//threadDoWork.Start();
}
}
/// <summary>
/// 处理方法
/// </summary>
static void doWork(object a)
{
//获取客户端信息
IPEndPoint ipEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
string address = ipEndPoint.Address.ToString();
//Console.WriteLine(address + ":连接成功");
//取消息
byte[] inBuffer = new byte[1024];
byte[] outBuffer = new byte[8];
string inBufferStr = "";
int rec = 0;
StringBuilder sb = new StringBuilder();
while (true)
{
try
{
rec = clientSocket.Receive(inBuffer);//如果没有消息为空 阻塞 当前循环
//收到的长度不够 忽略此次数据
if (rec <= 8)
{
continue;
}
int ll = inBuffer[4] + inBuffer[5] * 255;
inBufferStr = Encoding.UTF8.GetString(inBuffer, 8, ll);
Console.WriteLine(inBufferStr);
//回复收到
outBuffer[4] = 0;
outBuffer[5] = 0;
outBuffer[6] = 0;
outBuffer[7] = 0;
outBuffer[3] = 0;
outBuffer[2] = 0;
outBuffer[1] = 0;
outBuffer[0] = 1;
clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
socketCount++;
Console.WriteLine(socketCount.ToString());
//break;
}
catch (SocketException es)
{
//clientSocket.Close();
return;
}
}
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace SocketClient
{
class Program
{
static Socket clientSocket;
static void Main(string[] args)
{
try
{
//将网络端点表示为IP地址和端口 用于socket侦听时绑定
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.33.29"), 4660);
clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//将Socket连接到服务器
clientSocket.Connect(ipep);
string outBufferStr;
//发送消息
outBufferStr = "123456789qwe|789654123|1|2015-04-22 10:51:34|6|test1|test2| ";
byte[] tempb = Encoding.UTF8.GetBytes(outBufferStr);
byte[] outBuffer = new byte[tempb.Length + 8];
//加功能和长度
outBuffer[0] = 1;
outBuffer[1] = 0;
outBuffer[2] = 0;
outBuffer[3] = 0;
outBuffer[4] = Convert.ToByte(tempb.Length % 255);
outBuffer[5] = Convert.ToByte(tempb.Length / 255);
outBuffer[6] = 0;
outBuffer[7] = 0;
for (int i = 0; i < tempb.Length; i++)
{
outBuffer[8 + i] = tempb[i];
}
// Byte[] inBuffer = new Byte[1024];
int kkk = 0;
while (kkk <= 10000)
{
clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
kkk++;
Thread.Sleep(1);
Console.WriteLine(kkk.ToString());
//Console.WriteLine("服务器响应:");
//接收服务器端信息
//clientSocket.Receive(inBuffer, 1024, SocketFlags.None);
//Console.WriteLine(Encoding.ASCII.GetString(inBuffer));
}
Console.WriteLine(kkk.ToString());
Console.ReadLine();
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
Console.ReadLine();
}
}
}
}
------解决思路----------------------
那有这么写的?长度不够也是数据啊,那能随便就不要了呢
------解决思路----------------------
Console.WriteLine("服务启动成功");
之后
要加上
Console.ReadLine();
啊
否则程序运行完了不退出了
------解决思路----------------------
还有,
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
应该写成
IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer);
你指定了一个IP,只侦听这个IP来的数据
那么其他IP来的数据当然不响应
------解决思路----------------------
还有既然是短连接,你recieve的时候要加ReadTimeOut啊
超时了赶紧进catch
否则某个客户端连接了但是不发送数据,你接收线程不永远阻塞住?
如果你想多客户端能够同时连接,要给每个子线程new一个socket对象(TCPClint)来接收不同客户端发送的数据
都用同一个Socket,数据不会错乱吗
总之你这代码问题很多,先解决了这几个问题,再有新的问题再想办法解决吧
------解决思路----------------------
1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。
起步也得用select吧
2. 异步模式比同步模式性能要好些
3..net的SocketAsyncEventArgs足够强大了,为何不用呢
------解决思路----------------------
至少有一个完全错误的严重问题,你的 clientSocket 应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。
最近由于业务的需要,Linux系统嵌入式设备往我做的服务程序发送数据。
速度奇慢,而且还是程序无响应。后来自己用C#写了一个客户端用来测试。已经用了线程池,不知道用法对不对。请大家帮忙看下。
服务端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace consoleSocketServer
{
class Program
{
static int socketCount = 0;
static Socket serverSocket;
static Socket clientSocket;
public static int clientcount = 0;
public int clientnum = 0;
static int listSQL = 0;
static bool asy = true;
public static Int32 portServer = 0;
public static string ipServer = "";
public static Thread threadSocketListen;
public static Thread threadDoWork;
public static Thread threadInsert;
public static int countsql = 0;
static void Main(string[] args)
{
IPAddress ipAddress;
portServer = 4660;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ipAddress = IPAddress.Parse("192.168.33.29");
ipServer = ipAddress.ToString();
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
Console.WriteLine("服务器IP:" + ipServer + " 端口:" + portServer);
serverSocket.Bind(localEndPoint);
serverSocket.Listen(20);
//设置线程池
ThreadPool.SetMaxThreads(4, 4);
//开启新的线程监听
threadSocketListen = new Thread(SocketListen);
threadSocketListen.Start();
Console.WriteLine("服务启动成功");
}
static void SocketListen()
{
while (true)
{
//接受客户端信息
clientSocket = serverSocket.Accept();
//开启处理线程
ThreadPool.QueueUserWorkItem(new WaitCallback(doWork));
//threadDoWork = new Thread(new ThreadStart(doWork));
//threadDoWork.Start();
}
}
/// <summary>
/// 处理方法
/// </summary>
static void doWork(object a)
{
//获取客户端信息
IPEndPoint ipEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
string address = ipEndPoint.Address.ToString();
//Console.WriteLine(address + ":连接成功");
//取消息
byte[] inBuffer = new byte[1024];
byte[] outBuffer = new byte[8];
string inBufferStr = "";
int rec = 0;
StringBuilder sb = new StringBuilder();
while (true)
{
try
{
rec = clientSocket.Receive(inBuffer);//如果没有消息为空 阻塞 当前循环
//收到的长度不够 忽略此次数据
if (rec <= 8)
{
continue;
}
int ll = inBuffer[4] + inBuffer[5] * 255;
inBufferStr = Encoding.UTF8.GetString(inBuffer, 8, ll);
Console.WriteLine(inBufferStr);
//回复收到
outBuffer[4] = 0;
outBuffer[5] = 0;
outBuffer[6] = 0;
outBuffer[7] = 0;
outBuffer[3] = 0;
outBuffer[2] = 0;
outBuffer[1] = 0;
outBuffer[0] = 1;
clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
socketCount++;
Console.WriteLine(socketCount.ToString());
//break;
}
catch (SocketException es)
{
//clientSocket.Close();
return;
}
}
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace SocketClient
{
class Program
{
static Socket clientSocket;
static void Main(string[] args)
{
try
{
//将网络端点表示为IP地址和端口 用于socket侦听时绑定
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.33.29"), 4660);
clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//将Socket连接到服务器
clientSocket.Connect(ipep);
string outBufferStr;
//发送消息
outBufferStr = "123456789qwe|789654123|1|2015-04-22 10:51:34|6|test1|test2| ";
byte[] tempb = Encoding.UTF8.GetBytes(outBufferStr);
byte[] outBuffer = new byte[tempb.Length + 8];
//加功能和长度
outBuffer[0] = 1;
outBuffer[1] = 0;
outBuffer[2] = 0;
outBuffer[3] = 0;
outBuffer[4] = Convert.ToByte(tempb.Length % 255);
outBuffer[5] = Convert.ToByte(tempb.Length / 255);
outBuffer[6] = 0;
outBuffer[7] = 0;
for (int i = 0; i < tempb.Length; i++)
{
outBuffer[8 + i] = tempb[i];
}
// Byte[] inBuffer = new Byte[1024];
int kkk = 0;
while (kkk <= 10000)
{
clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
kkk++;
Thread.Sleep(1);
Console.WriteLine(kkk.ToString());
//Console.WriteLine("服务器响应:");
//接收服务器端信息
//clientSocket.Receive(inBuffer, 1024, SocketFlags.None);
//Console.WriteLine(Encoding.ASCII.GetString(inBuffer));
}
Console.WriteLine(kkk.ToString());
Console.ReadLine();
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
Console.ReadLine();
}
}
}
}
------解决思路----------------------
//收到的长度不够 忽略此次数据
if (rec <= 8)
{
continue;
}
那有这么写的?长度不够也是数据啊,那能随便就不要了呢
------解决思路----------------------
Console.WriteLine("服务启动成功");
之后
要加上
Console.ReadLine();
啊
否则程序运行完了不退出了
------解决思路----------------------
还有,
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
应该写成
IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer);
你指定了一个IP,只侦听这个IP来的数据
那么其他IP来的数据当然不响应
------解决思路----------------------
还有既然是短连接,你recieve的时候要加ReadTimeOut啊
超时了赶紧进catch
否则某个客户端连接了但是不发送数据,你接收线程不永远阻塞住?
如果你想多客户端能够同时连接,要给每个子线程new一个socket对象(TCPClint)来接收不同客户端发送的数据
都用同一个Socket,数据不会错乱吗
总之你这代码问题很多,先解决了这几个问题,再有新的问题再想办法解决吧
------解决思路----------------------
1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。
起步也得用select吧
2. 异步模式比同步模式性能要好些
3..net的SocketAsyncEventArgs足够强大了,为何不用呢
------解决思路----------------------
至少有一个完全错误的严重问题,你的 clientSocket 应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。