我正在C#中创建一个聊天客户端,以便在localhost上进行演示。
以下是相关代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
static List<TcpListener> garabage_collection_preventor = new List<TcpListener>();
static Dictionary<IPEndPoint, bool> address_dictionary = new Dictionary<IPEndPoint, bool>();
static int port_increment = 9999;
static int client_id = 0;
void start_listening()
{
while (true)
{
TcpListener listen = new TcpListener(IPAddress.Any, port_increment);
garabage_collection_preventor.Add(listen);
listen.Start();
TcpClient client = listen.AcceptTcpClient();
IPEndPoint temp_end = ((IPEndPoint)listen.LocalEndpoint);
address_dictionary.Add(temp_end, false);
port_increment++;
new Thread(new ParameterizedThreadStart(connection_stuff)).Start(client);
}
}
void writer(object ob,int end_point)
{
StreamWriter write = ob as StreamWriter;
while (true)
{
foreach (KeyValuePair<IPEndPoint, bool> value in address_dictionary)
{
IPEndPoint index = value.Key;
int temp = value.Key.Port;
if (temp == end_point)
{
while (address_dictionary[index] == true)
{
write.WriteLine(msg_box.Text);
}
}
}
}
}
void reader(StreamReader read)
{
while (true)
{
MessageBox.Show(read.ReadLine());
}
}
void connection_stuff(object ob)
{
TcpClient client = ob as TcpClient;
int writer_identification_endpoint = ((IPEndPoint)client.Client.LocalEndPoint).Port;
NetworkStream stream = client.GetStream();
StreamReader read = new StreamReader(stream);
StreamWriter write = new StreamWriter(stream);
ThreadStart port_passing = delegate { writer(write, writer_identification_endpoint); };
Thread thread = new Thread(port_passing);
reader(read);
thread.Start();
}
public Form1()
{
InitializeComponent();
}
private void send_Click(object sender, EventArgs e)
{
int end_point = int.Parse(port.Text);
foreach (KeyValuePair<IPEndPoint, bool> value in address_dictionary)
{
IPEndPoint index = value.Key;
int temp = value.Key.Port;
if (temp == end_point)
{
address_dictionary[index] = true;
}
}
}
private void listener_Click(object sender, EventArgs e)
{
new Thread(start_listening).Start();
listener.Enabled = false;
}
}
}
现在问题是第一个客户端可以轻松连接程序并发送该程序可以轻松读取的消息。但是,每个后续客户端都无法连接。
我知道我不应该创建一个TCPListener,但问题是我必须在localhost和端口号上演示程序是区分客户端的唯一真正方法。
所以请告诉我这段代码出了什么问题我已经把头撞在墙上好几个小时了。
修改
当英语不是第一语言时会发生这种情况:)此代码(目前尚未完成)将成为聊天客户端。此代码的每个实例都能够与此相同代码的其他实例进行通信。任何数量的实例都应该能够与任意数量的实例连接(例如,如果双击程序5次,那么现在将有5个实例可以相互通信)。
现在的问题是每个实例都有相同的IP地址(因为它们都在同一台机器上运行)。问题是如何说实例1假设连接到实例4,这里不能使用ip,因为实例2,3和5也将具有相同的IP地址。所以我要做的是将实例1与实例4连接,使用IP地址和PORT而不是仅使用IP地址,就像使用单个TCPListener一样。
答案 0 :(得分:5)
尝试在start_listening例程中将这三行代码移到while(true)循环之外。
TcpListener listen = new TcpListener(IPAddress.Any, port_increment);
garabage_collection_preventor.Add(listen);
listen.Start();
您只需要一个侦听器,您可以从中接受许多不同的连接。
答案 1 :(得分:0)
试试这样:
void start_listening()
{
TcpListener listen = new TcpListener(IPAddress.Any, port_increment);
garabage_collection_preventor.Add(listen);
listen.Start();
while (true)
{
TcpClient client = listen.AcceptTcpClient();
// etc
}
}
也就是说,一旦你创建了你的监听器,它就会在循环中运行,接受来自客户端的传入连接。
编辑:您遇到的问题是因为您的模拟存在缺陷。在现实世界中,每个聊天服务器在一个已知的端口号上的单个O / S实例中运行。由于您自己只有一个O / S实例,因此无法在该实例上运行多个聊天服务器,而是在同一端口上进行监听。但是这样的事情可能会起作用,即你需要两个循环,第一个创建你的监听器,第二个内部循环让每个监听器接受多个客户端。注意:这些循环需要退出条件!
void start_listening()
{
while (true)
{
TcpListener listen = new TcpListener(IPAddress.Any, port_increment);
garabage_collection_preventor.Add(listen);
listen.Start();
while (true)
{
TcpClient client = listen.AcceptTcpClient();
IPEndPoint temp_end = ((IPEndPoint)listen.LocalEndpoint);
address_dictionary.Add(temp_end, false);
new Thread(new ParameterizedThreadStart(connection_stuff)).Start(client);
}
port_increment++;
}
}