您的位置:首页 > 理论基础 > 计算机网络

.net网络编程之一:Socket编程

2009-03-18 10:28 381 查看
SocketThread类代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.Sockets;

namespace ServerSocket
{
/// <summary>
/// 用于处理客户端请求的Socket
/// 作者:周公
/// 编写时间:2009-03-18
/// </summary>
public class SocketThread:IDisposable
{
private Socket socket;
private Thread thread;
private bool isListening = false;
private string text;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="socket">用于处理客户端应答的Socket</param>
public SocketThread(Socket socket)
{
this.socket = socket;
isListening = true;
thread = new Thread(new ThreadStart(Work));
thread.Start();
}

public void Work()
{
byte[] buffer=new byte[1024];
while (isListening)
{
int receivedLength = socket.Receive(buffer);
text=System.Text.Encoding.UTF8.GetString(buffer,0,receivedLength);
//<EOF>是自定义的协议,表示中止消息交流
if (text.IndexOf("<EOF>") > -1)
{
isListening=false;
socket.Send(new byte[] { 0 });
}
else
{
//Console.WriteLine("接收到的数据:" + text);
//根据客户端的请求获取相应的响应信息
string message = GetMessage(text);
//将响应信息以字节的方式发送到客户端
socket.Send(Encoding.UTF8.GetBytes(message));
}
}
}
private string GetMessage(string request)
{
string message = string.Empty;
//Console.WriteLine("Message=" + request);
switch (request)
{
case "date": message = "服务器日期:"+DateTime.Now.ToString("yyyy-MM-dd"); break;
case "time": message ="服务器时间:"+ DateTime.Now.ToString("HH:mm:ss"); break;
case "datetime": message = "服务器日期时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); break;
case "year": message = "服务器年份:" + DateTime.Now.Year.ToString(); break;
case "month": message = "服务器月份:" + DateTime.Now.Month.ToString(); break;
case "day": message = "这是本月第" + DateTime.Now.Day.ToString()+"天"; break;
default: message = "不正确的参数"; break;
}
return message;
}

#region IDisposable 成员

public void Dispose()
{
isListening = false;
if (thread != null)
{
if (thread.ThreadState != ThreadState.Aborted)
{
thread.Abort();
}
thread = null;
}
if (socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}

#endregion

}
}


客户端请求的Socket代码如下(与前面两个类位于不同的控制台项目中):

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ServerSocket
{
/// <summary>
/// 客户端请求的Socket包装类
/// 作者:周公
/// 编写时间:2009-03-18
/// </summary>
public class ClientSocket:IDisposable
{
private Socket sender = null;
private bool isListening = false;
//定义用于接收服务器响应的存储区.
private byte[] bytes = new byte[1024];
//用于终止Soket的消息
private string shutDownMessage = "<EOF>";

public ClientSocket()
{
try
{
//设置要连接的主机信息并使用11000作为监听端口.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);

// 创建一个TCP/IP协议的socket连接
sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sender.Connect(remoteEP);
isListening = true;
}
catch (Exception ex)
{

Console.WriteLine(ex.ToString());
}
}

public void StartClient()
{
// 连接到远程主机,并捕获所有信息
try
{

Console.WriteLine("连接到主机{0}",
sender.RemoteEndPoint.ToString());
OutParameters();
string consoleMessage = Console.ReadLine();
while (isListening&&!string.IsNullOrEmpty(consoleMessage))
{
consoleMessage = consoleMessage.ToLower();
if (consoleMessage == "bye")
{
SendShutDownMessage();
}
else
{
string resultMessage=SendMessage(consoleMessage);
Console.WriteLine(resultMessage);
OutParameters();
consoleMessage = Console.ReadLine();
//Console.WriteLine("consoleMessage=" + consoleMessage);
}
}

}
catch (ArgumentNullException ane)
{
Console.WriteLine("参数异常 : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("出现Socket异常: {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("出现了异常 : {0}", e.ToString());
}

}
/// <summary>
/// 向远程主机发送信息
/// </summary>
/// <param name="message">要发送的信息</param>
public string SendMessage(string message)
{
byte[] buffer = Encoding.UTF8.GetBytes(message);
sender.Send(buffer);
int count=sender.Receive(bytes);
return Encoding.UTF8.GetString(bytes, 0, count);
}
/// <summary>
/// 向服务器发送关闭Socket信息,并中止与服务器的连接
/// </summary>
public void SendShutDownMessage()
{
SendMessage(shutDownMessage);
Console.WriteLine("已经关闭与服务器的连接");
isListening = false;
Environment.Exit(0);
}

private void OutParameters()
{
Console.WriteLine("参数说明:");
Console.WriteLine("获取服务器日期:date");
Console.WriteLine("获取服务器时间:time");
Console.WriteLine("获取服务器日期时间:datetime");
Console.WriteLine("获取服务器年份:year");
Console.WriteLine("获取服务器月份:month");
Console.WriteLine("获取服务器天数:day");
Console.WriteLine("关闭连接:bye");
Console.WriteLine("请输入你要进行的操作:");
}

public static int Main(String[] args)
{
ClientSocket client = new ClientSocket();
client.StartClient();
return 0;
}

#region IDisposable 成员

public void Dispose()
{
isListening = false;
if (sender != null)
{
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}

#endregion
}
}


上面的三个类位于两个控制台项目中ServerSocket类和SocketThread类位于同一个类库项目中,其中ClientSocket类位于另一个控制台项目中,编译之后会生成两个exe文件,运行的时候首先运行服务器端exe程序以便监听,再运行客户端exe程序。这个程序运行的效果如下:



注意,在终止程序的时候首先在客户端向服务器发送一个自定义的字符串“<EOF>”,在客户端使用命令行参数“bye”就是发送这个字符串的,这样就会正确终止服务器端响应Socket及正确关闭客户端请求的Socket,否则有可能抛出异常。
以上仅仅是演示了如何使用Socket进行编程,如果要传输文件的话,可能需要更多类似于关闭Socket的自定义字符串用以控制了。另外使用Socket来传输数据是比较高效的,但是传输控制相对来说要麻烦一点,针对网络中一些特殊场合的数据传输,可以使用特定的传输协议,在这个系列的后续文章中会继续介绍网络编程的有关知识。程序代码稍后整理之后提供下载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐