TcpClient问题

挨踢民工的乐章 2009-03-30 10:20:52

public void StartServer()
{
ServerThread = new Thread(new ThreadStart(startServer));
ServerThread.Start();
}
private void startServer()
{
IPAddress myIP = Dns.GetHostAddresses(Dns.GetHostName())[0];
Listener = new TcpListener(myIP,Port);
Listener.Start();
while(isStart)
{
try
{
MySocket = Listener.AcceptSocket();
}
catch
{
//经常抛出异常,无法处理
}

System.Net.EndPoint tempRemoteEP = MySocket.RemoteEndPoint;

byte[] tempBuffer = new byte[BUFFER_SIZE];
int len = 0, hasRecived = 0;
try
{
ReceiveFileStream = new FileStream(Att.FileSaveName, FileMode.Create, FileAccess.Write);
do
{
len = MySocket.ReceiveFrom(tempBuffer, ref tempRemoteEP);
ReceiveFileStream.Write(tempBuffer, 0, len);
hasRecived += len;
} while (len > 0);
MessageBox.Show("完成!"); //这里的代码经常访问不到 }
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.ToString());
}
finally
{
ReceiveFileStream.Close();
MySocket.Close();
}
}
}


TcpLisener运行机制的问题:如果上面没有while语句的话,是不是只能接受一次连接?(也就是说我写while语句是多余的?)

这个代码怎么才能优化的好点?

如果能写个StopServer()函数,那就更谢谢了。。。

...全文
198 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
如果同一个时间只接受一个连接的话,没必要在另一个线程处理Socket吧?
  • 打赏
  • 举报
回复
感觉还是有问题。。。

如果不用异步的方法,启动新线程来处理Socket,怎么传递MySocket这个参数?

就算它是个全局的变量,如果又来一个连接的话它就会变。。。不知道怎么传才可以。。
编程有钱人了 2009-04-01
  • 打赏
  • 举报
回复
近来我也研究这个
帮你UP
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 smallfz 的回复:]
至少 MySocket = Listener.AcceptSocket() 没有报告异常。
[/Quote]

在打开程序然后立刻关闭时候有异常抛出。。。

14楼,我确实是用混了。。。我认为一样那


再问一个问题:

如果我想提高传送的效率,要怎么做?再用个BufferedStream来封装一下?

我发现如果改变
byte[] Bytes = new byte[1024]; //改大这个数组
Socket RemoteSocket = null;
我把它改成512*1024(0.5M)传输速度提高了很多。

还有什么方法可以提高传输速率?


wartim 2009-04-01
  • 打赏
  • 举报
回复
你如果用TCPListener,就用它的AcceptTcpClient,
如果用Socket,就用AcceptSocket,
你怎么混着用
这是我写以前写过的一个Socket接收,连接用非阻塞的,接收用阻塞的
Socket LocalSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint EP = new IPEndPoint(Dns.GetHostByName(IP).AddressList[0], _ReceivePort);
int milliStart = Environment.TickCount, milliEnd = milliStart;
bool Finished = false;
byte[] Bytes = new byte[1024];
Socket RemoteSocket = null;

try
{
LocalSocket.Blocking = false;
LocalSocket.Bind(EP);
LocalSocket.Listen(1);
while (milliEnd - milliStart < _TimeOut)
{
try
{
RemoteSocket = LocalSocket.Accept();
Finished = true;
break;
}
catch
{
milliEnd = Environment.TickCount;
}
}
if (!Finished)
return String.Empty;
LocalSocket.Blocking = true;
do
try
{
RemoteSocket.ReceiveTimeout = _TimeOut;
RemoteSocket.Receive(Bytes);
}
catch
{
return String.Empty;
}
while (LocalSocket.Available != 0);
IPEndPoint RemoteEP = (IPEndPoint)RemoteSocket.LocalEndPoint;
ReceiveRemoteIP = RemoteEP.Address.ToString();
return Encoding.Default.GetString(Bytes, 0, 1024).Trim();
}
finally
{
if (RemoteSocket != null)
{
RemoteSocket.Shutdown(SocketShutdown.Both);
RemoteSocket.Close();
RemoteSocket = null;
}
LocalSocket.Close();
LocalSocket = null;
}
smallfz 2009-04-01
  • 打赏
  • 举报
回复
至少 MySocket = Listener.AcceptSocket() 没有报告异常。
smallfz 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 benben2301 的回复:]
如果同一个时间只接受一个连接的话,没必要在另一个线程处理Socket吧?
[/Quote]

那样就像你的代码那样就可以了。

我把你的代码拿来运行了下,没有问题。
  • 打赏
  • 举报
回复
是要连接多次,

还有注意一下,接收完数据后有个MessageBox,访问不到,不知道为什么。。。。

MySocket = Listener.AcceptSocket();
这句经常抛出异常,特别是在快速打开程序后,又关闭时。。怎么处理?
wartim 2009-03-31
  • 打赏
  • 举报
回复
再补充一下,是异步阻塞
wartim 2009-03-31
  • 打赏
  • 举报
回复
写错了,是tcplistener
wartim 2009-03-31
  • 打赏
  • 举报
回复
tcpclient默认是阻塞式,会停在 MySocket = Listener.AcceptSocket();直到收到套接字再往下走
编程有钱人了 2009-03-31
  • 打赏
  • 举报
回复
up
smallfz 2009-03-31
  • 打赏
  • 举报
回复
接楼上,漏掉一个重要的方法DoClientConnectedCallBack


/// <summary>
/// 接受新的客户端连接
/// </summary>
/// <param name="result"></param>
private void DoClientConnectedCallBack(IAsyncResult result) {
TcpListener listener = result.AsyncState as TcpListener;
TcpClient client = null;
try {
client = listener.EndAcceptTcpClient(result);
} catch {
} finally {
_clientconnected.Set();
}
if (client != null) {
ProcessClient(client); /* 处理与客户端的交互 */
client.Close();
}
}
smallfz 2009-03-31
  • 打赏
  • 举报
回复
1,AcceptSocket方法是会阻塞当前线程,直到接收到一个客户端连接请求并建立,才返回这个连接的socket对象。因为这个socket对象是用来收发数据的,所以如果你想让收发操作完成之前服务器侦听的端口继续接受新的客户端连接,你就必须让收发操作在另一个线程运行。也就是说,AcceptSocket返回回来的socket必须在另一个线程进行处理并关闭。

2,如果要避免这种方式,可以用异步方式进行,也就是用BeginAcceptSocket或者BeginAcceptTcpClient方法,使用这个方法需要配合一个同步信号对象(暂时这么称呼吧),例如ManualResetEvent。

自己写的一点大致代码,希望有帮助:)


Thread _listenthread = null;
bool _onStopping = false;
TcpListener _server = null;
ManualResetEvent _clientconnected = new ManualResetEvent(false);

/// <summary>
/// 侦听主线程
/// </summary>
private void ListeningMain() {
_server = new TcpListener(hostip, Port);
_server.Start();

while (!_onStopping) {
_clientconnected.Reset();
_server.BeginAcceptTcpClient(new AsyncCallback(DoClientConnectedCallBack), _server);
_clientconnected.WaitOne();
}
}

/// <summary>
/// 关闭侦听端口
/// </summary>
private void ClearSocket() {
try {
_clientconnected.Set();
} catch {
}
if (_server != null) {
try {
_server.Stop();
} catch {
}
}
}

/// <summary>
/// 关闭侦听端口和侦听线程
/// </summary>
private void ShutdownListenThread() {
_onStopping = true;
ClearSocket();
if (_listenthread != null) {
if (_listenthread.ThreadState == ThreadState.Running) {
_listenthread.Abort();
_listenthread.Join(3 * 1000);
}
}
}

/// <summary>
/// 启动侦听线程
/// </summary>
private void StartListenThread() {
ShutdownListenThread();
_onStopping = false;
_listenthread = new Thread(new ThreadStart(ListeningMain));
_listenthread.Start();
}
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fengmingxing 的回复:]
acceptsocket应该单独在一个线程里,不能和socket收发放在一个线程里
[/Quote]

为什么?
fengmingxing 2009-03-31
  • 打赏
  • 举报
回复
acceptsocket应该单独在一个线程里,不能和socket收发放在一个线程里
wenbin 2009-03-30
  • 打赏
  • 举报
回复
你是想要连接一次吗?
如果是那么就不需要最外面的while循环了,
如果要有多个客户端连接,那么需要对连接进来的每个socket进行处理


关闭方法
public void StopServer()
{
isStart = false;
if(ServerThread != null && ServerThread.IsAlive) ServerThread.Join();
ServerThread = null;
}

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧