【发布时间】:2014-06-02 19:17:11
【问题描述】:
我对@987654321@ 和Thread Safe 套接字的一些概念有一些疑问。我有 2 个类,一个 服务器类 和一个 客户端类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// Loosely inspired on http://msdn.microsoft.com/en-us/library/fx6588te.aspx
namespace AsynchronousSockets
{
class Server
{
class StateObject
{
public Socket connection = null;
// Note that I use a very small buffer size
// for this example. Normally you'd like a much
// larger buffer. But this small buffer size nicely
// demonstrates getting the entire message in multiple
// pieces.
public const int bufferSize = 100000;
public byte[] buffer = new byte[bufferSize];
public int expectedMessageLength = 0;
public int receivedMessageLength = 0;
public byte[] message = null;
}
static ManualResetEvent acceptDone = new ManualResetEvent(false);
const int listenPort = 2500;
static void Main(string[] args)
{
Console.Out.WriteLine("This is the server");
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, listenPort);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
acceptDone.Reset();
Console.Out.WriteLine("Listening on port {0}", listenPort);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
acceptDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static void AcceptCallback(IAsyncResult ar)
{
try
{
acceptDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.connection = handler;
handler.BeginReceive(state.buffer, 0, StateObject.bufferSize,
SocketFlags.None, new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static void ReadCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.connection;
int read = handler.EndReceive(ar);
if (read > 0)
{
Console.Out.WriteLine("Read {0} bytes", read);
if (state.expectedMessageLength == 0)
{
// Extract how much data to expect from the first 4 bytes
// then configure buffer sizes and copy the already received
// part of the message.
state.expectedMessageLength = BitConverter.ToInt32(state.buffer, 0);
state.message = new byte[state.expectedMessageLength];
Array.ConstrainedCopy(state.buffer, 4, state.message, 0, Math.Min(StateObject.bufferSize - 4, state.expectedMessageLength - state.receivedMessageLength));
state.receivedMessageLength += read - 4;
}
else
{
Array.ConstrainedCopy(state.buffer, 0, state.message, state.receivedMessageLength, Math.Min(StateObject.bufferSize, state.expectedMessageLength - state.receivedMessageLength));
state.receivedMessageLength += read;
}
// Check if we received the entire message. If not
// continue listening, else close the connection
// and reconstruct the message.
if (state.receivedMessageLength < state.expectedMessageLength)
{
handler.BeginReceive(state.buffer, 0, StateObject.bufferSize,
SocketFlags.None, new AsyncCallback(ReadCallback), state);
}
else
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.Out.WriteLine("Received message: \n");
Console.Out.WriteLine(Encoding.UTF8.GetString(state.message));
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using Client;
using System.Management;
// Loosely inspired on http://msdn.microsoft.com/en-us/library/bew39x2a.aspx
namespace AsynchronousSockets
{
class Program
{
static readonly IPAddress serverIP = IPAddress.Loopback;
const int serverPort = 2500;
static ManualResetEvent connectDone = new ManualResetEvent(false);
static ManualResetEvent sendDone = new ManualResetEvent(false);
static void Main(string[] args)
{
Console.Out.WriteLine("This is the client");
Console.Out.WriteLine("Write the message to send. End with an emtpy line to start the transmisison. \n");
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
for (int i = 0; i <= 10000; i++)
{
String message = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") + " : Message sended by " + userName + ".";
Console.Out.WriteLine("Sending message: ...\n");
Console.Out.Write(message);
Console.Out.Write("\n");
Thread.Sleep(10);
Console.Out.WriteLine("Sleeping ...\n");
SendMessageAsync(message);
}
Console.Out.WriteLine("Sending finished by " + userName + "! \n");
}
static void SendMessageAsync(string message)
{
// Initiate connecting to the server
Socket connection = Connect();
// block this thread until we have connected
// normally your program would just continue doing other work
// but we've got nothing to do :)
connectDone.WaitOne();
Console.Out.WriteLine("Connected to server");
// Start sending the data
SendData(connection, message);
sendDone.WaitOne();
Console.Out.WriteLine("Message successfully sent");
}
static Socket Connect()
{
try
{
IPEndPoint serverAddress = new IPEndPoint(serverIP, serverPort);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(serverAddress, new AsyncCallback(ConnectCallback), client);
return client;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
static void SendData(Socket connection, string message)
{
try
{
byte[] data = Encoding.UTF8.GetBytes(message);
// We store how much data the server should expect
// in the first 4 bytes of the data we're going to send
byte[] head = BitConverter.GetBytes(data.Length);
byte[] total = new byte[data.Length + head.Length];
head.CopyTo(total, 0);
data.CopyTo(total, head.Length);
connection.BeginSend(total, 0, total.Length, 0, new AsyncCallback(SendCallBack), connection);
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
}
private static void SendCallBack(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytes = client.EndSend(ar);
Console.Out.WriteLine("A total of {0} bytes were sent to the server", bytes);
sendDone.Set();
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
}
}
}
如您所见,一旦client.exe 启动,如果server.exe 正在运行,它将收到Client 类发送的一些消息。
for (int i = 0; i <= 10000; i++)
{
String message = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") + " : Message sended by " + userName + ".";
Console.Out.WriteLine("Sending message: ...\n");
Console.Out.Write(message);
Console.Out.Write("\n");
Thread.Sleep(10);
Console.Out.WriteLine("Sleeping ...\n");
SendMessageAsync(message);
}
这个循环将执行 10000 次,循环之间的暂停时间为 10 毫秒。我从 3 个地方启动了 3 个客户端(不同的 windows 用户同时登录),服务器日志是:
......
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user1.
Listening on port 2500
Listening on port 2500
Listening on port 2500
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user2.
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user3.
Listening on port 2500
Listening on port 2500
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user2.
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user3.
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
02-06-2014 11:24:30 : Message sended by MyComputer-PC\user1.
Listening on port 2500
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 8 bytes
Read 7 bytes
Received message:
......
在所有 3 个客户端停止后,我在“记事本++”中打开日志文件并计算以下结果:
count "MyComputer-PC\user1" => 8903
count "MyComputer-PC\user2" => 8464
count "MyComputer-PC\user3" => 8990
为什么会这样?一些数据已经丢失,它应该呈现 10.000 10.000 10.000 ...
我该如何解决这个问题?
我想问的另一件事是如何使套接字线程安全。
编辑
当套接字被拒绝时,我实际上得到了这个日志
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
Sending message: ...
03-06-2014 09:35:58 : Message sended by MyComputer-PC\User1.
Sleeping ...
connection.Connected False
connection.Blocking True
Connected to server
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Message successfully sent
谢谢。
【问题讨论】:
-
你为什么搁置我的帖子?我想我没有违反 stackoverflow 的原则
-
由于列出的原因而暂停。范围太广了。
-
它是什么?请解释一下,我可能会一遍又一遍地犯同样的错误。谢谢。
-
关闭原因在此处列出。你只需要阅读它。
-
There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.所以我写了很多?这是不可能的......我想做的只是提供足够的细节,而不是像其他人所说的那样说这不起作用......
标签: c# asp.net .net multithreading sockets