环境:VS2008 + C#窗体程序
情况:1. 一个服务器端程序
2. 多个GPS终端设备
3. 可能多个客户端软件
上面2和3都通过TCP协议连接到服务器端程序,其中2是设备,只发送到服务器端就可以了。3是软件客户端,不但要发送,同时也能接受服务器端发送过来的数据。
服务器端程序永远在接收2的设备发送过来的数据。
现在我要实现这样一种需求:
在3的客户端软件界面上,选择一种GPS设备编号,然后将此编号发送给服务器端程序,服务器端程序接收到3的客户端发送过来的数据后,将实时接收到的该GPS设备数据转发给3的客户端软件这个该怎么实现?请各位高手帮我实现以下。
下面程序是服务器端接收2和3的两种客户端数据的多线程监听和接收方式(两种客户端发送的协议数据结构一样)。//服务器为每一个连接客户端产生一个线程,这样接受多个连接:
private TcpListener tcpListener;
private Thread listenThread;public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient(); //create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream(); byte[] message = new byte[4096];
int bytesRead; while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
} if (bytesRead == 0)
{
//the client has disconnected from the server
break;
} //message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}多线程threadsocket跨线程访问 跨线程传参数
情况:1. 一个服务器端程序
2. 多个GPS终端设备
3. 可能多个客户端软件
上面2和3都通过TCP协议连接到服务器端程序,其中2是设备,只发送到服务器端就可以了。3是软件客户端,不但要发送,同时也能接受服务器端发送过来的数据。
服务器端程序永远在接收2的设备发送过来的数据。
现在我要实现这样一种需求:
在3的客户端软件界面上,选择一种GPS设备编号,然后将此编号发送给服务器端程序,服务器端程序接收到3的客户端发送过来的数据后,将实时接收到的该GPS设备数据转发给3的客户端软件这个该怎么实现?请各位高手帮我实现以下。
下面程序是服务器端接收2和3的两种客户端数据的多线程监听和接收方式(两种客户端发送的协议数据结构一样)。//服务器为每一个连接客户端产生一个线程,这样接受多个连接:
private TcpListener tcpListener;
private Thread listenThread;public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient(); //create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream(); byte[] message = new byte[4096];
int bytesRead; while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
} if (bytesRead == 0)
{
//the client has disconnected from the server
break;
} //message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}多线程threadsocket跨线程访问 跨线程传参数
5000用于处理接收多个gps设备的协议数据,5001用于接收发送数据给多个客户端(自己定义数据协议).
例TcpClienta[100]是gps设备连接过来的,TcpClientb[100]是客户端连接;
TcpClienta[x]收到gps数据后可以通过TcpClientb[y]发给客户端,当然要判断2个连接上的设备ID一致.
public class Server
{
//服务器为每一个连接客户端产生一个线程,这样接受多个连接:
private TcpListener tcpListener;
private Thread listenThread;
private SortedList<string, TcpClient> clientList; public Server()
{
this.clientList = new SortedList<string, TcpClient>();
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
} protected void AddClient(string gpsID, TcpClient client)
{
lock (clientList)
{
clientList.Add(gpsID, client);
}
} protected TcpClient GetClient(string gpsID)
{
TcpClient client = null;
lock (clientList)
{
if (clientList.ContainsKey(gpsID))
{
client = clientList[gpsID];
}
}
return client;
} private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
} private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream(); byte[] message = new byte[4096];
int bytesRead;
string gpsID = ""; while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
//TBD: if Client, Get GPSID
gpsID = "";
AddClient(gpsID, tcpClient);
//TBD: if GPS, GetGPSData
byte[] gpsData = null;
string currentGPSID = "";
TcpClient tcpClientByGPS = GetClient(currentGPSID);
if (tcpClientByGPS != null)
{
tcpClientByGPS.GetStream().BeginWrite(gpsData, 0, gpsData.Length, null, null);
}
}
catch
{
//a socket error has occured
break;
} if (bytesRead == 0)
{
//the client has disconnected from the server
break;
} //message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
}
{
lock (clientList)
{
if (!clientList.ContainsKey(gpsID))
{
clientList.Add(gpsID, client);
}
}
}
你能帮我也改一下吗?按照楼主的需求就行private void ServerForm_Load(object sender, EventArgs e)
{
//测试线程
Thread SoceketTestThread = new Thread(new ThreadStart(StartListening));
SoceketTestThread.Start();
//实例化
Set_Text = new set_Text(set_ListViewCarFlowText);
}
/// <summary>
/// 开启端口监听线程
/// </summary>
private void StartListening()
{
listener = new TcpListener(IPAddress.Parse(m_serverIP), int.Parse(m_serverPort));
listener.Start();
while (StartListeningFlg)
{
try
{
//一旦在该端口号监听到信息,则启动一个新的线程
Socket s = listener.AcceptSocket();
//判断是否处在连接状态中
if (s.Connected == true)
{
clientsocket = s;
clientservice = new Thread(new ThreadStart(ServiceClient));
clientservice.Start();
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return;
}
}
//停止监听
listener.Stop();
}
/// <summary>
/// 开启对客户端信息的接收处理线程
/// </summary>
private void ServiceClient()
{
try
{
while (ServiceClientFlg)
{
Byte[] buffer = new Byte[1024];
//设置该socket为阻止模式
clientsocket.Blocking = true;
//获取客户端IP地址
IPEndPoint ipe = (IPEndPoint)clientsocket.RemoteEndPoint;
//接收二进制byte数据
int intRec = clientsocket.Receive(buffer);
if (intRec < 1)
{
clientsocket.Close();
//委托相关,用以该线程操控主线程上的控件
listViewCarFlow.Invoke(Set_Text, new object[] { "\r\n" + "已经断开连接" });
break;
}
//将二进制数据信息转换成字符串型
string strReceiveMessage = System.Text.Encoding.ASCII.GetString(buffer);
//委托相关,用以该线程操控主线程上的控件
listViewCarFlow.Invoke(Set_Text, new object[] { "\r\n" + strReceiveMessage });
//发送到客户端
byte[] bs = Encoding.ASCII.GetBytes("i have recevied from" + strIP);
clientsocket.Send(bs, bs.Length, 0);
}
}
catch (Exception ex)
{
clientsocket.Close();
}
}
这个代码里似乎没有关于我要的东西吧?
我要的需求是
1 GPS设备可以跟服务器通讯
2 客户端软件可以跟服务器通讯
这两个你应该都写了
3 客户端软件界面上如果选择某个GPS设备,则服务器接收到这个GPS设备的数据后转发到客户端软件
这个过程应该是客户端软件发送一个连接请求到服务器(发送GPSID),由于服务器一直在监听(就是一直在接收GPS设备的数据),这个时候比较一下两个GPSID是否相同,如果相同,则将此GPSID对应的数据发给客户端软件
这个第3点你没写吧?我关键是这个不会,如何在线程间转发呢?
写完善的代码确实很难,不过catchdream朋友加的代码也确实没有实现楼主第三个需求
估计楼主是最关键的部分不会写吧。
协议格式倒不用太注意,直接socket.Send(buffer..)传就好了,意思明了就行。
我只会那种线程独立的,用全局变量,然后1线程传值给2线程的
楼主这种模式的,我也不会写:)也期待有人能写点大概的代码,学习学习。
基本就是补充下面代码的TBD: //blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
//TBD: if Client, Get GPSID
gpsID = "";
AddClient(gpsID, tcpClient);
//TBD: if GPS, GetGPSData
byte[] gpsData = null;
string currentGPSID = "";
TcpClient tcpClientByGPS = GetClient(currentGPSID);
if (tcpClientByGPS != null)
{
tcpClientByGPS.GetStream().BeginWrite(gpsData, 0, gpsData.Length, null, null);
}