C#Socket网络编程大全

4 篇文章 0 订阅

1.简单服务器端
/*
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.Threading;
private static int port = %%2;
private static Thread thThreadRead;
private static TcpListener TcpListen;
private static bool bListener = true;
private static Socket stRead;
*/
private static void Listen()
{
try
{
TcpListen = new TcpListener(port);
TcpListen.Start();
stRead = TcpListen.AcceptSocket();
EndPoint tempRemoteEP = stRead.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
string sHostName = host.HostName;
while (bListener)
{
stRead.Send(Encoding.ASCII.GetBytes(%%1));
string sTime = DateTime.Now.ToShortTimeString();
Byte[] byRead = new Byte[1024];
int iRead = stRead.ReceiveFrom(byRead, ref tempRemoteEP);
Byte[] byText = new Byte[iRead];
Array.Copy(byRead, 0, byText, 0, iRead);
string line = System.Text.Encoding.Default.GetString(byRead);
}
}
catch (System.Security.SecurityException)
{
//监听失败
}
}
thThreadRead = new Thread(new ThreadStart(Listen));
thThreadRead.Start();

2.简单客户端
/*
using System.Data;
using System.Net.Sockets;
using System.Net;
private static IPEndPoint dateTimeHost;
*/
string hostIPString=%%1;
string hostPortString=%%2;
IPAddress hostIP=IPAddress.Parse(hostIPString);
dateTimeHost=new IPEndPoint(hostIP,Int32.Parse(hostPortString));
Socket conn=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
conn.Connect(dateTimeHost);
int bytes=0;
Byte[] RecvBytes=new Byte[256];
bytes=conn.Receive(RecvBytes,RecvBytes.Length,0);
string RecvString=Encoding.ASCII.GetString(RecvBytes,0,bytes);
Console.WriteLine(RecvString);
conn.Shutdown(SocketShutdown.Both);
conn.Close();

3.获得本机IP
//using System.Net;
IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;
string %%1=null;
for (int i = 0; i < addressList.Length; i++)
{
%%1 += addressList[i].ToString();
}

4.端对端通信
/*
using System.Net;
using System.Net.Sockets;
*/
UdpClient client=new UdpClient(%%2);
IPAddress a=IPAddress.Parse("127001");
IPEndPoint receivePoint=new IPEndPoint(a,%%2);
IPAddress HostIP=null;
byte[] sendData=Encoding.UTF8.GetBytes(%%3);
byte[] recData;
try{
HostIP=IPAddress.Parse(%%1);
}
catch {
recData=client.Receive(ref receivePoint);
%%3=Encoding.UTF8.GetString(recData);
client.Send(sendData,sendData.Length,%%4,%%2);
client.Close();
}
IPEndPoint host=new IPEndPoint(HostIP,%%2);
recData=client.Receive(ref receivePoint);
%%3=Encoding.UTF8.GetString(recData);
client.Close();

5.点对点通信
/*
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.Threading;
*/
Thread th;
TcpListener tpListen1;
bool listenerRun=true;
NetworkStream tcpStream;
StreamWriter reqStreamW;
TcpClient tcpc;
Socket skSocket;
protected void Listen()
{
try{
tpListen1=new TcpListener(Int32.Parse(%%2));
tpListen1.Start();
skSocket=tpListen1.AcceptSocket();
EndPoint tempRemoteEP=skSocket.RemoteEndPoint;
IPEndPoint tempRemoteIP=(IPEndPoint)tempRemoteEP;
IPHostEntry host=Dns.GetHostByAddress(tempRemoteIP.Address);
string HostName=host.HostName;
while(listenerRun)
{
Byte[] stream=new Byte[1024];
string time=DateTime.Now.ToString();
int i=skSocket.ReceiveFrom(stream,ref tempRemoteEP);
string %%5=Encoding.UTF8.GetString(stream);
//指定编码,从缓冲区中解析出内容
//time+" "+HostName+":"
}
}
catch(Security.SecurityException)
{
//防火墙安全错误!
}
try{
string sMsg=%%4;
string MyName=Dns.GetHostName();
reqStreamW=new StreamWriter(tcpStream);
reqStreamW.Write(sMsg);
reqStreamW.Flush();
string time=DateTime.Now.ToString();
//显示传送的数据和时间
//time+" "+MyName+":"
//sMsg
}
catch(Exception)
{
//无法发送信息到目标计算机!
}

protected override void Dispose(bool disposing)
{
try{
listenerRun=false;
th.Abort();
th=null;
tpListen1.Stop();
skSocket.Close();
tcpc.Close();
}
catch{}
if(disposing && component!=null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}

6.UDP对时服务器端
/*
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
*/
public void start_server()
{
while(true)
{
byte[] recData=server.Receive(ref receivePoint);
ASCIIEncoding encode=new ASCIIEncoding();
string Read_str=encode.GetString(recData));
string[] tem=Read_str.Split('/');
byte[] sendData=encode.GetBytes(DataTime.Now.ToString());
server.Send(sendData,sendData.Length,temp[0],Int32.Parse(temp[1]));
}
}
UdpClient server=new UdpClient(%%1);
IPEndPoint receivePoint=new IPEndPoint(new IPAddress("127001",%%1);
Thread startServer=new Thread(new ThreadStart(start_server));
startServer.Start();

protected override void Dispose(bool disposing)
{
try{
startServer.Abort();
server.Close();
}
catch{}
if(disposing && component!=null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}

7.UDP对时客户端
/*
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
*/
[DllImport("Kernel32.dll")]
private static bool SetSystemTime(SystemTime time);
public class SystemTime
{
public short year;
public short Month;
public short DayOfWeek;
public short Day;
public short Hour;
public short Minute;
public short Second;
public short Milliseconds;
}
UdpClient client=new UdpClient(%%2);
IPEndPoint receivePoint=new IPEndPoint(a,%%2);
IPAddress a=new IPAddress.Parse("127001");
string timeString=DateTime.Now.ToString();
DataTime temp;
IPAddress HostIP;
bool continueLoop=true;
while(continueLoop)
{
string hostName=Dns.GetHostName();
Text.ASCIIEncoding encode=new Text.ASCIIEncoding();
string sendString=hostName+"/"+%%2.ToString();
byte[] sendData=encode.GetBytes(sendString);
byte[] recData;
try{
HostIP=IPAddress.Parse(%%1);
}
catch {
client.Send(sendData,sendData.Length,%%1,%%2);
recData=client.Receive(ref receivePoint);
timeString=encode.GetString(recData);
client.Close();
continueLoop=false;
return;
}
IPEndPoint host=new IPEndPoint(HostIP,%%2);
client.Send(sendData,sendData.Length,host);
recData=client.Receive(ref receivePoint);
timeString=encode.GetString(recData);
client.Close();
continueLoop=false;
}
try{
temp=DataTime.Parse(timeString);
}
catch {
return;
}
SystemTime st=new SystemTime();
st.year=(short)temp.Year;
st.Month=(short)temp.Month;
st.DayOfWeek=(short)temp.DayOfWeek;
st.Day=(short)temp.Day;
st.Hour=Conver.ToInt16(temp.Hour);
if(st.Hour>=12)
{
st.Hour-=(short)8;
}
else if(st.Hour>=8)
{
st.Hour-=(short)8;
}
else
{
st.Hour+=(short)16;
}
st.Minute=Convert.ToInt16(temp.Minute);
st.Second=Convert.ToInt16(temp.Second);
st.Milliseconds=Convert.ToInt16(temp.Milliseconds);
if(SetSystemTime(st))
{
//修改成功
}
else
{
//修改不成功
}

8.点对点传输文件
using System.Sockes;
/*
System.Sockes命名空间了实现 Berkeley 套接字接口。通过这个类,我们可以实现网络计算机之间的消息传输和发送.而在我下面要讨论的这个议题里,我们将讨论的是用套节子实现文件的传输.这种方法有别于FTP协议实现的的文件传输方法,利用ftp的方法需要一个专门的服务器和客户端,无疑于我们要实现的点对点的文件传输太为复杂了一些。在这里,我们实现一个轻量级的方法来实现点对点的文件传输,这样就达到了intenet上任何两个计算机的文件共享。
在两台计算机传输文件之前,必需得先有一台计算机建立套节子连接并绑定一个固定得端口,并在这个端口侦听另外一台计算机的连接请求。
*/
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
socket.Blocking = true ;
IPEndPoint computernode1 = new IPEndPoint(serverIpadress, 8080);
socket.Bind(computernode1);
socket.Listen(-1);
//当有其他的计算机发出连接请求的时候,被请求的计算机将对每一个连接请求分配一个线程,用于处理文件传输和其他服务。

while (true)
{
clientsock = socket.Accept();
if ( clientsock.Connected )
{
Thread tc = new Thread(new ThreadStart(listenclient));
tc.Start();
}
}
//下面的代码展示了listenclient方法是如何处理另外一台计算机发送过来的请求。首先并对发送过来的请求字符串作出判断,看看是何种请求,然后决定相应的处理方法。
void listenclient()
{
Socket sock = clientsock ;
try
{
while ( sock != null )
{
byte[] recs = new byte[32767];
int rcount = sock.Receive(recs,recs.Length,0) ;
string message = System.Text.Encoding.ASCII.GetString(recs) ;
//对message作出处理,解析处请求字符和参数存储在cmdList 中
execmd=cmdList[0];
sender = null ;
sender = new Byte[32767];
string parm1 = "";
//目录列举
if ( execmd == "LISTING" )
{
ListFiles(message);
continue ;
}
//文件传输
if ( execmd == "GETOK" )
{
cmd = "BEGINSEND " + filepath + " " + filesize ;
sender = new Byte[1024];
sender = Encoding.ASCII.GetBytes(cmd);
sock.Send(sender, sender.Length , 0 );
//转到文件下载处理
DownloadingFile(sock);
continue ;
}
}
}
catch(Exception Se)
{
string s = Se.Message;
Console.WriteLine(s);
}
}
//至此,基本的工作已经完成了,下面我们看看如何处理文件传输的。
while(rdby < total && nfs.CanWrite)
{
//从要传输的文件读取指定长度的数据
len =fin.Read(buffed,0,buffed.Length) ;
//将读取的数据发送到对应的计算机
nfs.Write(buffed, 0,len);
//增加已经发送的长度
rdby=rdby+len ;
}
从上面的代码可以看出是完成文件转换成FileStream 流,然后通过NetworkStream绑定对应的套节子,最后调用他的write方法发送到对应的计算机。
我们再看看接受端是如何接受传输过来的流,并且转换成文件的:
NetworkStream nfs = new NetworkStream(sock) ;
try
{
//一直循环直到指定的文件长度
while(rby < size)
{
byte[] buffer = new byte[1024] ;
//读取发送过来的文件流
int i = nfs.Read(buffer,0,buffer.Length) ;
fout.Write(buffer,0,(int)i) ;
rby=rby+i ;
}
fout.Close();
}
catch(Exception){}
/*
从上面可以看出接受与发送恰好是互为相反的过程,非常简单。
至此,单方向的文件传输就完成了,只需要在每个对等的节点上同时实现上面的发送和接受的处理代码就可以做到互相传输文件了。
*/

9.发送邮件
//using System.Net.Mail;
string strSmtpServer=%%1; //"100.100.100.100"
string strFrom=%%2; //"someone@xxx.com"
string strFromPass=%%3; //"someone@xxx.com"
string strto=%%4; //"xxxx"
string strSubject=%%5;//"webtest"
string strBody=%%6; TextBox1
SmtpClient client = new SmtpClient(strSmtpServer);
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential(strFrom, strFromPass);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
MailMessage message = new MailMessage(strFrom, strto, strSubject, strBody);
Attachment attachment = new Attachment("c://log.log");
message.Attachments.Add(attachment);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
client.Send(message);

10.接收邮件
/*
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.IO;
*/
// 类名:Pop3
// 功能:接收电子邮件

namespace ZTSX.Email
{
/// <summary>
/// Pop3 的摘要说明。
/// </summary>
public class Pop3
{
private string mstrHost = null; //主机名称或IP地址
private int mintPort = 110; //主机的端口号(默认为110)
private TcpClient mtcpClient = null; //客户端
private NetworkStream mnetStream = null; //网络基础数据流
private StreamReader m_stmReader = null; //读取字节流
private string mstrStatMessage = null; //执行STAT命令后得到的消息(从中得到邮件数)

/// <summary>
/// 构造函数
/// </summary>
/// <remarks>一个邮件接收对象</remarks>
public Pop3()
{
}

/// <summary>
/// 构造函数
/// </summary>
/// <param name="host">主机名称或IP地址</param>
public Pop3(string host)
{
mstrHost = host;
}

/// <summary>
/// 构造函数
/// </summary>
/// <param name="host">主机名称或IP地址</param>
/// <param name="port">主机的端口号</param>
/// <remarks>一个邮件接收对象</remarks>
public Pop3(string host,int port)
{
mstrHost = host;
mintPort = port;
}

#region 属性

/// <summary>
/// 主机名称或IP地址
/// </summary>
/// <remarks>主机名称或IP地址</remarks>
public string HostName
{
get{return mstrHost;}
set{mstrHost = value;}
}

/// <summary>
/// 主机的端口号
/// </summary>
/// <remarks>主机的端口号</remarks>
public int Port
{
get{return mintPort;}
set{mintPort = value;}
}

#endregion

#region 私有方法

/// <summary>
/// 向网络访问的基础数据流中写数据(发送命令码)
/// </summary>
/// <param name="netStream">可以用于网络访问的基础数据流</param>
/// <param name="command">命令行</param>
/// <remarks>向网络访问的基础数据流中写数据(发送命令码)</remarks>
private void WriteToNetStream(ref NetworkStream netStream,String command)
{
string strToSend = command + "/r/n";
byte[] arrayToSend = System.Text.Encoding.ASCII.GetBytes(strToSend.ToCharArray());
netStream.Write(arrayToSend,0,arrayToSend.Length);
}

/// <summary>
/// 检查命令行结果是否正确
/// </summary>
/// <param name="message">命令行的执行结果</param>
/// <param name="check">正确标志</param>
/// <returns>
/// 类型:布尔
/// 内容:true表示没有错误,false为有错误
/// </returns>
/// <remarks>检查命令行结果是否有错误</remarks>
private bool CheckCorrect(string message,string check)
{
if(message.IndexOf(check) == -1)
return false;
else
return true;
}

/// <summary>
/// 邮箱中的未读邮件数
/// </summary>
/// <param name="message">执行完LIST命令后的结果</param>
/// <returns>
/// 类型:整型
/// 内容:邮箱中的未读邮件数
/// </returns>
/// <remarks>邮箱中的未读邮件数</remarks>
private int GetMailNumber(string message)
{
string[] strMessage = message.Split(' ');
return Int32.Parse(strMessage[1]);
}

/// <summary>
/// 得到经过解码后的邮件的内容
/// </summary>
/// <param name="encodingContent">解码前的邮件的内容</param>
/// <returns>
/// 类型:字符串
/// 内容:解码后的邮件的内容
/// </returns>
/// <remarks>得到解码后的邮件的内容</remarks>
private string GetDecodeMailContent(string encodingContent)
{
string strContent = encodingContent.Trim();
string strEncode = null;

int iStart = strContent.IndexOf("Base64");
if(iStart == -1)
throw new Pop3Exception("邮件内容不是Base64编码,请检查");
else
{
strEncode = strContent.Substring(iStart + 6,strContent.Length - iStart - 6);
try
{
return SX.Encode.TransformToString(strEncode);
}
catch(SX.EncodeException exc)
{
throw new Pop3Exception(exc.Message);
}
}
}

#endregion

/// <summary>
/// 与主机建立连接
/// </summary>
/// <returns>
/// 类型:布尔
/// 内容:连接结果(true为连接成功,false为连接失败)
/// </returns>
/// <remarks>与主机建立连接</remarks>
public bool Connect()
{
if(mstrHost == null)
throw new Exception("请提供SMTP主机名称或IP地址!");
if(mintPort == 0)
throw new Exception("请提供SMTP主机的端口号");
try
{
mtcpClient = new TcpClient(mstrHost,mintPort);
mnetStream = mtcpClient.GetStream();
m_stmReader = new StreamReader(mtcpClient.GetStream());

string strMessage = m_stmReader.ReadLine();
if(CheckCorrect(strMessage,"+OK") == true)
return true;
else
return false;
}
catch(SocketException exc)
{
throw new Pop3Exception(exc.ToString());
}
catch(NullReferenceException exc)
{
throw new Pop3Exception(exc.ToString());
}
}

#region Pop3命令

/// <summary>
/// 执行Pop3命令,并检查执行的结果
/// </summary>
/// <param name="command">Pop3命令行</param>
/// <returns>
/// 类型:字符串
/// 内容:Pop3命令的执行结果
/// </returns>
private string ExecuteCommand(string command)
{
string strMessage = null; //执行Pop3命令后返回的消息

try
{
//发送命令
WriteToNetStream(ref mnetStream,command);

//读取多行
if(command.Substring(0,4).Equals("LIST") || command.Substring(0,4).Equals("RETR") || command.Substring(0,4).Equals("UIDL")) //记录STAT后的消息(其中包含邮件数)
{
strMessage = ReadMultiLine();

if(command.Equals("LIST")) //记录LIST后的消息(其中包含邮件数)
mstrStatMessage = strMessage;
}
//读取单行
else
strMessage = m_stmReader.ReadLine();

//判断执行结果是否正确
if(CheckCorrect(strMessage,"+OK"))
return strMessage;
else
return "Error";
}
catch(IOException exc)
{
throw new Pop3Exception(exc.ToString());
}
}

/// <summary>
/// 在Pop3命令中,LIST、RETR和UIDL命令的结果要返回多行,以点号(.)结尾,
/// 所以如果想得到正确的结果,必须读取多行
/// </summary>
/// <returns>
/// 类型:字符串
/// 内容:执行Pop3命令后的结果
/// </returns>
private string ReadMultiLine()
{
string strMessage = m_stmReader.ReadLine();
string strTemp = null;
while(strMessage != ".")
{
strTemp = strTemp + strMessage;
strMessage = m_stmReader.ReadLine();
}
return strTemp;
}

//USER命令
private string USER(string user)
{
return ExecuteCommand("USER " + user) + "/r/n";
}

//PASS命令
private string PASS(string password)
{
return ExecuteCommand("PASS " + password) + "/r/n";
}

//LIST命令
private string LIST()
{
return ExecuteCommand("LIST") + "/r/n";
}

//UIDL命令
private string UIDL()
{
return ExecuteCommand("UIDL") + "/r/n";
}

//NOOP命令
private string NOOP()
{
return ExecuteCommand("NOOP") + "/r/n";
}

//STAT命令
private string STAT()
{
return ExecuteCommand("STAT") + "/r/n";
}

//RETR命令
private string RETR(int number)
{
return ExecuteCommand("RETR " + number.ToString()) + "/r/n";
}

//DELE命令
private string DELE(int number)
{
return ExecuteCommand("DELE " + number.ToString()) + "/r/n";
}

//QUIT命令
private void Quit()
{
WriteToNetStream(ref mnetStream,"QUIT");
}

/// <summary>
/// 收取邮件
/// </summary>
/// <param name="user">用户名</param>
/// <param name="password">口令</param>
/// <returns>
/// 类型:字符串数组
/// 内容:解码前的邮件内容
/// </returns>
private string[] ReceiveMail(string user,string password)
{
int iMailNumber = 0; //邮件数

if(USER(user).Equals("Error"))
throw new Pop3Exception("用户名不正确!");
if(PASS(password).Equals("Error"))
throw new Pop3Exception("用户口令不正确!");
if(STAT().Equals("Error"))
throw new Pop3Exception("准备接收邮件时发生错误!");
if(LIST().Equals("Error"))
throw new Pop3Exception("得到邮件列表时发生错误!");

try
{
iMailNumber = GetMailNumber(mstrStatMessage);

//没有新邮件
if(iMailNumber == 0)
return null;
else
{
string[] strMailContent = new string[iMailNumber];

for(int i = 1 ; i <= iMailNumber ; i++)
{
//读取邮件内容
strMailContent[i - 1] = GetDecodeMailContent(RETR(i));
}
return strMailContent;
}
}
catch(Pop3Exception exc)
{
throw new Pop3Exception(exc.ToString());
}
}

#endregion


/// <summary>
/// 收取邮件
/// </summary>
/// <param name="user">用户名</param>
/// <param name="password">口令</param>
/// <returns>
/// 类型:字符串数组
/// 内容:解码前的邮件内容
/// </returns>
///<remarks>收取邮箱中的未读邮件</remarks>
public string[] Receive(string user,string password)
{
try
{
return ReceiveMail(user,password);
}
catch(Pop3Exception exc)
{
throw new Pop3Exception(exc.ToString());
}
}

/// <summary>
/// 断开所有与服务器的会话
/// </summary>
/// <remarks>断开所有与服务器的会话</remarks>
public void DisConnect()
{
try
{
Quit();
if(m_stmReader != null)
m_stmReader.Close();
if(mnetStream != null)
mnetStream.Close();
if(mtcpClient != null)
mtcpClient.Close();
}
catch(SocketException exc)
{
throw new Pop3Exception(exc.ToString());
}
}

/// <summary>
/// 删除邮件
/// </summary>
/// <param name="number">邮件号</param>
public void DeleteMail(int number)
{
//删除邮件
int iMailNumber = number + 1;
if(DELE(iMailNumber).Equals("Error"))
throw new Pop3Exception("删除第" + iMailNumber.ToString() + "时出现错误!");
}

}
}

11.多线程阻塞通信

12.多线程非阻塞通信

13.多线程文件断点续传
//Send.dsw
//Thead.h
// 线程对象封装
//
#ifndef _THREAD_INCLUDE_
#define _THREAD_INCLUDE_

class CThread
{
private:
static DWORD WINAPI ThreadProc(LPVOID pVoid);
protected:
BOOL m_bTerminated; // 线程是否终止的标志

virtual void Execute(void) = 0;
public:
HANDLE m_hThread; // 线程句柄

CThread(void);
~CThread(void);

void Resume(void);
void Terminate(void);
HANDLE GetThreadHandle(void);
};

#endif // #ifndef _THREAD_INCLUDE_

//Thead.cpp
// 线程对象封装
//
#include "stdafx.h"
#include "Thread.h"

CThread::CThread(void)
{
m_bTerminated = FALSE;

DWORD dwThreadID;
m_hThread = CreateThread(NULL, 0, ThreadProc, this, CREATE_SUSPENDED, &dwThreadID);
}

CThread::~CThread(void)
{
CloseHandle(m_hThread);
m_hThread = NULL;
}

DWORD CThread::ThreadProc(LPVOID pVoid)
{
((CThread *)(pVoid))->Execute();

return 0;
}

void CThread::Resume(void)
{
ResumeThread(m_hThread);
}

void CThread::Terminate(void)
{
m_bTerminated = TRUE;
}

HANDLE CThread::GetThreadHandle(void)
{
return m_hThread;
}

m_pTcpClient = new CTcpClient(this);
m_strServerIp = "127.0.0.1";
m_nPort = 8000;
m_dwPackageSize = 1024;
m_strFileName = "d://a.pdf";
UpdateData(FALSE);

m_pTcpClient->SetOnSocketSendErr(OnSocketSendErr);
m_pTcpClient->SetOnSocketRecvErr(OnSocketRecvErr);
m_pTcpClient->SetOnSocketClose(OnSocketClose);
m_pTcpClient->SetOnOneNetMsg(OnOneNetMsg);
m_pTcpClient->SetOnSendFileSucc(OnSendFileSucc);
m_pTcpClient->SetOnSendFileFail(OnSendFileFail);
m_pTcpClient->SetOnSendFileRefuseRecv(OnSendFileRefuseRecv);
m_pTcpClient->SetOnSendFileCancelRecv(OnSendFileCancelRecv);
m_pTcpClient->SetOnSendFileRecvFail(OnSendFileRecvFail);
m_pTcpClient->SetOnSendFileProgress(OnSendFileProgress);
CStatic m_ctlCnnStatus;
CStatic m_ctlInfo;
DWORD m_dwPackageSize;
CString m_strServerIp;
int m_nPort;
CString m_strFileName;
CString m_strMsg;

void CSendDlg::OnConnect()
{
if(!UpdateData())
return;


m_pTcpClient->SetAddr((char *)(LPCTSTR)m_strServerIp);
m_pTcpClient->SetPort(m_nPort);
m_pTcpClient->SetPackageSize(m_dwPackageSize);

m_ctlCnnStatus.SetWindowText("请等待...");
if(!m_pTcpClient->Connect())
m_ctlCnnStatus.SetWindowText("连接失败!");
else
m_ctlCnnStatus.SetWindowText("已连接");
}

void CSendDlg::OnDisconnect()
{
m_pTcpClient->Disconnect();
m_ctlCnnStatus.SetWindowText("断开连接");
}

void CSendDlg::OnSendFile()
{
if(!UpdateData())
return;

m_pTcpClient->SetPackageSize(m_dwPackageSize);
if(!m_pTcpClient->SendFile((char *)(LPCTSTR)m_strFileName))
AfxMessageBox("发生文件失败");
}

void CSendDlg::OnSendMsg(void)
{
char s[99999];

if(!UpdateData())
return;


sprintf(s, "@00000001%s", m_strMsg);
m_pTcpClient->SendNetMsg(s, strlen(s) - 6);
}

void CSendDlg::OnSocketSendErr(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("发送数据出错");
}

void CSendDlg::OnSocketRecvErr(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("接收数据出错");
}

void CSendDlg::OnSocketClose(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("断开连接");
}

void CSendDlg::OnOneNetMsg(void *pNotifyObj, char *Msg, int nMsgLen)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
char s[9999];
CString strInfo;

strncpy(s, Msg, nMsgLen);
s[nMsgLen] = 0;
strInfo = s;

pSendDlg->DispInfo(strInfo);
}

void CSendDlg::OnSendFileSucc(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileSucc");
}

void CSendDlg::OnSendFileFail(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileFail");
}

// 接收方拒绝接收文件
void CSendDlg::OnSendFileRefuseRecv(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileRefuseRecv");
}

// 接收方拒绝文件
void CSendDlg::OnSendFileCancelRecv(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileCancelRecv");
}

// 接收方取消接收
void CSendDlg::OnSendFileRecvFail(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileRecvFail");
}

void CSendDlg::OnSendFileProgress(void *pNotifyObj, int nSentBytes, int nTotalBytes)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("%d / %d", nSentBytes, nTotalBytes);
pSendDlg->DispInfo(strInfo);
}

void CSendDlg::DispInfo(CString strInfo)
{
m_ctlInfo.SetWindowText(strInfo);
}

void CSendDlg::OnCancelSend()
{
m_pTcpClient->CancelSendFile();
}

void CSendDlg::OnDestroy()
{
CDialog::OnDestroy();

m_pTcpClient->Disconnect();
}
delete m_pTcpClient;

//Recv.dsw
#include "Shlwapi.h"

// 判断文件是否存在
BOOL IsFileExists(char *pszPathName);
// 创建多层目录,成功返回TRUE,识别返回FALSE
BOOL ForceDirectories(char *pszDir);
// 扩展文件操作
BOOL DeleteFileEx(char *szPathName, BOOL bAllowUndo = FALSE);
BOOL RenameFileEx(char *szOldPathName, char *szNewPathName);
BOOL MoveFileEx(char *szSrcPathName, char *szDstPathName);
BOOL CopyFileEx(char *szSrcPathName, char *szDstPathName);
// 重新启动操作系统
BOOL RebootWindows();
// 设置程序是否在操作系统启动后自动运行
void SetAutoRun(BOOL bEnable);
BOOL ShutDownWin98();
BOOL ShutDownWinNT();

BOOL IsLegalFileName(char *szFileName);
m_pTcpServer1 = new CTcpServer(this);
m_pTcpServer1->SetBindAddr("");
m_pTcpServer1->SetPort(8000);
m_pTcpServer1->SetOnAccept(OnAccept);
m_pTcpServer1->SetOnAcceptErr(OnAcceptErr);
m_pTcpServer1->SetOnSocketConnect(OnSocketConnect);
m_pTcpServer1->SetOnSocketDisconnect(OnSocketDisconnect);
m_pTcpServer1->SetOnSocketSendErr(OnSocketSendErr);
m_pTcpServer1->SetOnSocketRecvErr(OnSocketRecvErr);
m_pTcpServer1->SetOnOneNetMsg(OnOneNetMsg);
m_pTcpServer1->SetOnRecvFileStart(OnRecvFileStart);
m_pTcpServer1->SetOnRecvFileProgress(OnRecvFileProgress);
m_pTcpServer1->SetOnRecvFileFail(OnRecvFileFail);
m_pTcpServer1->SetOnRecvFileSucc(OnRecvFileSucc);
m_pTcpServer1->SetOnRecvFileCancel(OnRecvFileCancel);
if(!m_pTcpServer1->StartAccept())
{
AfxMessageBox("开始服务失败");
return FALSE;
}

void CRecvDlg::OnAccept(void *pNotifyObj, SOCKET hSocket, BOOL &bAccept)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
strInfo.Format("OnAccept-%d", hSocket);

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnAcceptErr(void *pNotifyObj, SOCKET hAccept)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
strInfo.Format("OnAcceptErr-%d", hAccept);

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnOneNetMsg(void *pNotifyObj, char *Msg, int nMsgLen)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
char s[10240];

memcpy(s, Msg, nMsgLen);
s[nMsgLen] = 0;
strInfo = (LPCTSTR)s;

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileStart(void *pNotifyObj, char *szPathName, BOOL &bRecv)
{
}

void CRecvDlg::OnRecvFileProgress(void *pNotifyObj, DWORD dwRecvedBytes, DWORD dwFileSize)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("%d / %d", dwRecvedBytes, dwFileSize);
pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileSucc(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileSucc";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileFail(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileFail";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileCancel(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileCancel";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::DispInfo(CString &strInfo)
{
m_ctlInfo1.SetWindowText(strInfo);
}

void CRecvDlg::DispCnnCount(void)
{
CString strCnnCount;

strCnnCount.Format("%d", m_pTcpServer1->GetClientCount());
m_ctlCnnCount.SetWindowText(strCnnCount);
}

void CRecvDlg::OnCancelRecv()
{
m_pTcpServer1->CancelAllRecvFile();
}

void CRecvDlg::OnSocketConnect(void *pNotifyObj, SOCKET hSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("OnSocketConnect-%d", hSocket);
pRecvDlg->DispInfo(strInfo);
pRecvDlg->DispCnnCount();
}

void CRecvDlg::OnSocketDisconnect(void *pNotifyObj, SOCKET hSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("OnSocketDisconnect-%d", hSocket);
pRecvDlg->DispInfo(strInfo);
pRecvDlg->DispCnnCount();
}

void CRecvDlg::OnSocketSendErr(void *pNotifyObj, CServerClientSocket *pServerClientSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnSocketSendErr";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnSocketRecvErr(void *pNotifyObj, CServerClientSocket *pServerClientSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnSocketRecvErr";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnCloseCnn()
{
}

void CRecvDlg::OnDestroy()
{
CDialog::OnDestroy();

m_pTcpServer1->CloseAllServerClientSocket();
}
delete m_pTcpServer1;
m_pTcpServer1 = NULL;

14.多线程多文件断点续传
//Send.dsw
//Thead.h
// 线程对象封装
//
#ifndef _THREAD_INCLUDE_
#define _THREAD_INCLUDE_

class CThread
{
private:
static DWORD WINAPI ThreadProc(LPVOID pVoid);
protected:
BOOL m_bTerminated; // 线程是否终止的标志

virtual void Execute(void) = 0;
public:
HANDLE m_hThread; // 线程句柄

CThread(void);
~CThread(void);

void Resume(void);
void Terminate(void);
HANDLE GetThreadHandle(void);
};

#endif // #ifndef _THREAD_INCLUDE_

//Thead.cpp
// 线程对象封装
//
#include "stdafx.h"
#include "Thread.h"

CThread::CThread(void)
{
m_bTerminated = FALSE;

DWORD dwThreadID;
m_hThread = CreateThread(NULL, 0, ThreadProc, this, CREATE_SUSPENDED, &dwThreadID);
}

CThread::~CThread(void)
{
CloseHandle(m_hThread);
m_hThread = NULL;
}

DWORD CThread::ThreadProc(LPVOID pVoid)
{
((CThread *)(pVoid))->Execute();

return 0;
}

void CThread::Resume(void)
{
ResumeThread(m_hThread);
}

void CThread::Terminate(void)
{
m_bTerminated = TRUE;
}

HANDLE CThread::GetThreadHandle(void)
{
return m_hThread;
}

m_pTcpClient = new CTcpClient(this);
m_strServerIp = "127.0.0.1";
m_nPort = 8000;
m_dwPackageSize = 1024;
m_strFileName = "d://a.pdf";
UpdateData(FALSE);

m_pTcpClient->SetOnSocketSendErr(OnSocketSendErr);
m_pTcpClient->SetOnSocketRecvErr(OnSocketRecvErr);
m_pTcpClient->SetOnSocketClose(OnSocketClose);
m_pTcpClient->SetOnOneNetMsg(OnOneNetMsg);
m_pTcpClient->SetOnSendFileSucc(OnSendFileSucc);
m_pTcpClient->SetOnSendFileFail(OnSendFileFail);
m_pTcpClient->SetOnSendFileRefuseRecv(OnSendFileRefuseRecv);
m_pTcpClient->SetOnSendFileCancelRecv(OnSendFileCancelRecv);
m_pTcpClient->SetOnSendFileRecvFail(OnSendFileRecvFail);
m_pTcpClient->SetOnSendFileProgress(OnSendFileProgress);
CStatic m_ctlCnnStatus;
CStatic m_ctlInfo;
DWORD m_dwPackageSize;
CString m_strServerIp;
int m_nPort;
CString m_strFileName;
CString m_strMsg;

void CSendDlg::OnConnect()
{
if(!UpdateData())
return;


m_pTcpClient->SetAddr((char *)(LPCTSTR)m_strServerIp);
m_pTcpClient->SetPort(m_nPort);
m_pTcpClient->SetPackageSize(m_dwPackageSize);

m_ctlCnnStatus.SetWindowText("请等待...");
if(!m_pTcpClient->Connect())
m_ctlCnnStatus.SetWindowText("连接失败!");
else
m_ctlCnnStatus.SetWindowText("已连接");
}

void CSendDlg::OnDisconnect()
{
m_pTcpClient->Disconnect();
m_ctlCnnStatus.SetWindowText("断开连接");
}

void CSendDlg::OnSendFile()
{
if(!UpdateData())
return;

m_pTcpClient->SetPackageSize(m_dwPackageSize);
if(!m_pTcpClient->SendFile((char *)(LPCTSTR)m_strFileName))
AfxMessageBox("发生文件失败");
}

void CSendDlg::OnSendMsg(void)
{
char s[99999];

if(!UpdateData())
return;


sprintf(s, "@00000001%s", m_strMsg);
m_pTcpClient->SendNetMsg(s, strlen(s) - 6);
}

void CSendDlg::OnSocketSendErr(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("发送数据出错");
}

void CSendDlg::OnSocketRecvErr(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("接收数据出错");
}

void CSendDlg::OnSocketClose(void *pNotifyObj, SOCKET hSocket)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
pSendDlg->m_ctlCnnStatus.SetWindowText("断开连接");
}

void CSendDlg::OnOneNetMsg(void *pNotifyObj, char *Msg, int nMsgLen)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
char s[9999];
CString strInfo;

strncpy(s, Msg, nMsgLen);
s[nMsgLen] = 0;
strInfo = s;

pSendDlg->DispInfo(strInfo);
}

void CSendDlg::OnSendFileSucc(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileSucc");
}

void CSendDlg::OnSendFileFail(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileFail");
}

// 接收方拒绝接收文件
void CSendDlg::OnSendFileRefuseRecv(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileRefuseRecv");
}

// 接收方拒绝文件
void CSendDlg::OnSendFileCancelRecv(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileCancelRecv");
}

// 接收方取消接收
void CSendDlg::OnSendFileRecvFail(void *pNotifyObj, char *szPathName)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;

pSendDlg->DispInfo("OnSendFileRecvFail");
}

void CSendDlg::OnSendFileProgress(void *pNotifyObj, int nSentBytes, int nTotalBytes)
{
CSendDlg *pSendDlg = (CSendDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("%d / %d", nSentBytes, nTotalBytes);
pSendDlg->DispInfo(strInfo);
}

void CSendDlg::DispInfo(CString strInfo)
{
m_ctlInfo.SetWindowText(strInfo);
}

void CSendDlg::OnCancelSend()
{
m_pTcpClient->CancelSendFile();
}

void CSendDlg::OnDestroy()
{
CDialog::OnDestroy();

m_pTcpClient->Disconnect();
}
delete m_pTcpClient;

//Recv.dsw
#include "Shlwapi.h"

// 判断文件是否存在
BOOL IsFileExists(char *pszPathName);
// 创建多层目录,成功返回TRUE,识别返回FALSE
BOOL ForceDirectories(char *pszDir);
// 扩展文件操作
BOOL DeleteFileEx(char *szPathName, BOOL bAllowUndo = FALSE);
BOOL RenameFileEx(char *szOldPathName, char *szNewPathName);
BOOL MoveFileEx(char *szSrcPathName, char *szDstPathName);
BOOL CopyFileEx(char *szSrcPathName, char *szDstPathName);
// 重新启动操作系统
BOOL RebootWindows();
// 设置程序是否在操作系统启动后自动运行
void SetAutoRun(BOOL bEnable);
BOOL ShutDownWin98();
BOOL ShutDownWinNT();

BOOL IsLegalFileName(char *szFileName);
m_pTcpServer1 = new CTcpServer(this);
m_pTcpServer1->SetBindAddr("");
m_pTcpServer1->SetPort(8000);
m_pTcpServer1->SetOnAccept(OnAccept);
m_pTcpServer1->SetOnAcceptErr(OnAcceptErr);
m_pTcpServer1->SetOnSocketConnect(OnSocketConnect);
m_pTcpServer1->SetOnSocketDisconnect(OnSocketDisconnect);
m_pTcpServer1->SetOnSocketSendErr(OnSocketSendErr);
m_pTcpServer1->SetOnSocketRecvErr(OnSocketRecvErr);
m_pTcpServer1->SetOnOneNetMsg(OnOneNetMsg);
m_pTcpServer1->SetOnRecvFileStart(OnRecvFileStart);
m_pTcpServer1->SetOnRecvFileProgress(OnRecvFileProgress);
m_pTcpServer1->SetOnRecvFileFail(OnRecvFileFail);
m_pTcpServer1->SetOnRecvFileSucc(OnRecvFileSucc);
m_pTcpServer1->SetOnRecvFileCancel(OnRecvFileCancel);
if(!m_pTcpServer1->StartAccept())
{
AfxMessageBox("开始服务失败");
return FALSE;
}

void CRecvDlg::OnAccept(void *pNotifyObj, SOCKET hSocket, BOOL &bAccept)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
strInfo.Format("OnAccept-%d", hSocket);

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnAcceptErr(void *pNotifyObj, SOCKET hAccept)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
strInfo.Format("OnAcceptErr-%d", hAccept);

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnOneNetMsg(void *pNotifyObj, char *Msg, int nMsgLen)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;
char s[10240];

memcpy(s, Msg, nMsgLen);
s[nMsgLen] = 0;
strInfo = (LPCTSTR)s;

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileStart(void *pNotifyObj, char *szPathName, BOOL &bRecv)
{
}

void CRecvDlg::OnRecvFileProgress(void *pNotifyObj, DWORD dwRecvedBytes, DWORD dwFileSize)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("%d / %d", dwRecvedBytes, dwFileSize);
pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileSucc(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileSucc";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileFail(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileFail";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnRecvFileCancel(void *pNotifyObj, char *szPathName)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnRecvFileCancel";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::DispInfo(CString &strInfo)
{
m_ctlInfo1.SetWindowText(strInfo);
}

void CRecvDlg::DispCnnCount(void)
{
CString strCnnCount;

strCnnCount.Format("%d", m_pTcpServer1->GetClientCount());
m_ctlCnnCount.SetWindowText(strCnnCount);
}

void CRecvDlg::OnCancelRecv()
{
m_pTcpServer1->CancelAllRecvFile();
}

void CRecvDlg::OnSocketConnect(void *pNotifyObj, SOCKET hSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("OnSocketConnect-%d", hSocket);
pRecvDlg->DispInfo(strInfo);
pRecvDlg->DispCnnCount();
}

void CRecvDlg::OnSocketDisconnect(void *pNotifyObj, SOCKET hSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo;

strInfo.Format("OnSocketDisconnect-%d", hSocket);
pRecvDlg->DispInfo(strInfo);
pRecvDlg->DispCnnCount();
}

void CRecvDlg::OnSocketSendErr(void *pNotifyObj, CServerClientSocket *pServerClientSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnSocketSendErr";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnSocketRecvErr(void *pNotifyObj, CServerClientSocket *pServerClientSocket)
{
CRecvDlg *pRecvDlg = (CRecvDlg *)pNotifyObj;
CString strInfo = "OnSocketRecvErr";

pRecvDlg->DispInfo(strInfo);
}

void CRecvDlg::OnCloseCnn()
{
}

void CRecvDlg::OnDestroy()
{
CDialog::OnDestroy();

m_pTcpServer1->CloseAllServerClientSocket();
}
delete m_pTcpServer1;
m_pTcpServer1 = NULL;

15.截取屏幕
/*
using System.Runtime.InteropServices;
[DllImport("GDI32.dll")]
public static extern bool BitBlt(int hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,int hdcSrc,int nXSrc,int nYSrc,int dwRop);
[DllImport("GDI32.dll")]
public static extern int CreateCompatibleBitmap(int hdc,int nWidth,int nHeight);
[DllImport("GDI32.dll")]
public static extern int CreateCompatibleDC(int hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteDC(int hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(int hObject);
[DllImport("GDI32.dll")]
public static extern int GetDeviceCaps(int hdc,int nIndex);
[DllImport("GDI32.dll")]
public static extern int SelectObject(int hdc,int hgdiobj);
[DllImport("User32.dll")]
public static extern int GetDesktopWindow();
[DllImport("User32.dll")]
public static extern int GetWindowDC(int hWnd);
[DllImport("User32.dll")]
public static extern int ReleaseDC(int hWnd,int hDC);
*/

// Captures the current on-screen representation using Windows API calls
public Bitmap CaptureScreen()
{
// Provides a pointer to the visual representation of the desktop window
int source= GetWindowDC(GetDesktopWindow());
// Secures the image using CreateCompatibleBitmap
int bitmap= CreateCompatibleBitmap(source, GetDeviceCaps(source,8), GetDeviceCaps(source,10));

int destination= CreateCompatibleDC(source);

SelectObject(destination, bitmap);
BitBlt(destination,0,0, GetDeviceCaps(source,8), GetDeviceCaps(source,10), source,0,0,0x00CC0020);
Bitmap image= GetImage(bitmap);
Cleanup(bitmap, source, destination);
return image;
}

private void Cleanup(int bitmap,int source,int destination)
{
ReleaseDC(GetDesktopWindow(), source);
DeleteDC(destination);
DeleteObject(bitmap);
}

private Bitmap GetImage(int hBitmap)
{
Bitmap image= new Bitmap(Image.FromHbitmap(new IntPtr(hBitmap)), Image.FromHbitmap(new IntPtr(hBitmap)).Width,
Image.FromHbitmap(new IntPtr(hBitmap)).Height);
return image;
}

16.聊天室服务器端逻辑
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Collections;
class Server
{
private static List<Socket> li = new ArrayList<Socket>();
private static TcpListener TcpListen;
private static Socket stRead;
public Server(int port)
{
try
{
TcpListen = new TcpListener(port);
TcpListen.Start();
}
catch (Exception) { }
}
public List<TcpListener> Li()
{
get{
return li;
};
set{
li=value;
};
}
public void start()
{
while (true)
{
Socket s;
try
{
stRead = TcpListen.AcceptSocket();
li.Add(TcpListen);
new Service(this, s).start();
}
catch (Exception e) { }
}

}
static void main(string[] args)
{
new Server(8888).start();
}
}

class Service
{
private static Socket stRead;
private static bool bListener = true;
private static TcpListener TcpListen;
public Service(Server server, Socket client)
{
TcpClient tcpc;
Socket stSend = null;
bool tcpConnect = false;
try
{
stSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint tempRemoteEP = stSend.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
EndPoint epTemp = (EndPoint)tempRemoteIP;
stSend.Connect(epTemp);
tcpConnect = true;
}
catch (Exception)
{
//MessageBox.Show("目标计算机拒绝了连接请求!");
}
finally
{
if (tcpConnect)
{
stSend.Close();
}
}
}
public static void run()
{
while (true)
{
stRead = TcpListen.AcceptSocket();
EndPoint tempRemoteEP = stRead.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
string sHostName = host.HostName;
while (bListener)
{
string sTime = DateTime.Now.ToShortTimeString();
Byte[] byRead = new Byte[1024];
int iRead = stRead.ReceiveFrom(byRead, ref tempRemoteEP);
Byte[] byText = new Byte[iRead];
Array.Copy(byRead, 0, byText, 0, iRead);
string line = System.Text.Encoding.Default.GetString(byRead);
}
}
}
static void Main(string[] args)
{
}
}

17.聊天室客户端逻辑
/*
类似qq聊天工具
你看看。。
这是客服端的代码:
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.Threading;
using System.Net;
using System.Net.Sockets;

namespace demo2
{
public partial class frmTouchWe : Form
{
Thread a;
//发送IP跟端口
private UdpClient udp = new UdpClient("127.0.0.1",9000);
//接收端口
private UdpClient udpSend = new UdpClient(8000);
private IPEndPoint ip = new IPEndPoint(IPAddress.Any,0);
public frmTouchWe()
{
InitializeComponent();
Form.CheckForIllegalCrossThreadCalls = false;
}

private void frmTouchWe_Load(object sender, EventArgs e)
{ //定义线程开始
a = new Thread(new ThreadStart(Run));
a.Start(); }


private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
//客服接收信息。弹出窗体
frmAnswerInfo answerInfo = new frmAnswerInfo();
answerInfo.Show(); }

private void button1_Click(object sender, EventArgs e)
{
//在自己的信息栏中显示自己的信息
lsbInfo.Items.Add(txtInfo.Text);
//用户信息内容
string Mes = txtInfo.Text;
//用户信息
string mes = "用户:"+Program.user.id+"("+Program.user.name+")"+" " + time;
//转换成字节
byte[] b = UTF8Encoding.UTF8.GetBytes(Mes);
byte[] bb = UTF32Encoding.UTF8.GetBytes(mes);
//发送信息
udp.Send(bb, bb.Length);
udp.Send(b, b.Length);
txtInfo.Text = "";
}
//循环接受客服发来的信息
private void Run()
{
while (true)
{
byte[] b = udpSend.Receive(ref ip);
string mes = UTF8Encoding.UTF8.GetString(b);
lsbInfo.Items.Add(mes);
}
}

private void button2_Click(object sender, EventArgs e)
{
this.Close();
}

private void button3_Click_1(object sender, EventArgs e)
{
//清空所有项
lsbInfo.Items.Clear();
}
}
}


下面是服务器端的代码
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.Threading;
using System.Net;
using System.Net.Sockets;

namespace demo2
{
public partial class frmAnswerInfo : Form
{
//定义一条线程,用来循环接收客户发来的信息
Thread a;
//定义另一条线程,用来升起窗体
Thread b;
//发送到信息的地址
private UdpClient udpSend = new UdpClient("127.0.0.1",8000);
//接收端口
private UdpClient udp = new UdpClient(9000);
private IPEndPoint ip = new IPEndPoint(IPAddress.Any,0);
public frmAnswerInfo()
{
InitializeComponent();
Form.CheckForIllegalCrossThreadCalls = false;
}
//循环接收信息
private void Run()
{
while (true)
{
byte[] b = udp.Receive(ref ip);
string mes = UTF8Encoding.UTF8.GetString(b);
lsbInfo.Items.Add(mes);
}
}

private void frmAnswerInfo_Load(object sender, EventArgs e)
{
//设置窗体的位置属性(窗体加载时候慢慢从右下角升上来~类似qq广告~~)
this.Top = Screen.PrimaryScreen.WorkingArea.Height;
this.Left = Screen.PrimaryScreen.WorkingArea.Width - this.Width;
//设置窗体的名字
a = new Thread(new ThreadStart(Run));

b = new Thread(new ThreadStart(run));
//开始线程
a.Start();
b.Start();
}
//用户点击谈话时显示该窗体
private void run()
{
while (true)
{
this.Top = this.Top - 10;
Thread.Sleep(100);
if (Screen.PrimaryScreen.WorkingArea.Height - this.Height >= this.Top)
{
break;
}
}
}
//发送按钮编码
private void button1_Click(object sender, EventArgs e)
{
//获取当前时间
DateTime time = DateTime.Now;
//在自己的信息栏中显示自己发出去的信息
lsbInfo.Items.Add("在线客服:"+time);
lsbInfo.Items.Add(txtInfo.Text);

//在客户端显示自己的信息标题
string mes = "在线客服:"+time;
//信息内容
string Mes = txtInfo.Text;
//发送信息标题
byte[] b = UTF8Encoding.UTF8.GetBytes(mes);
//发送信息内容
byte[] bb = UTF8Encoding.UTF8.GetBytes(Mes);
udpSend.Send(b, b.Length);
udpSend.Send(bb,bb.Length);
txtInfo.Text = "";
}

private void button2_Click(object sender, EventArgs e)
{
this.Close();
}

private void button3_Click(object sender, EventArgs e)
{
//清除所有项
lsbInfo.Items.Clear();
}
}
}
*/

18.克隆对象
http://www.legalsoft.com.cn/docs/docs/16/986.html
/// <summary>
/// BaseObject类是一个用来继承的抽象类。
/// 每一个由此类继承而来的类将自动支持克隆方法。
/// 该类实现了Icloneable接口,并且每个从该对象继承而来的对象都将同样地
/// 支持Icloneable接口。
/// </summary>
public abstract class BaseObject : ICloneable
{
/// <summary>
/// 克隆对象,并返回一个已克隆对象的引用
/// </summary>
/// <returns>引用新的克隆对象</returns>
public object Clone()
{
//首先我们建立指定类型的一个实例
object newObject = Activator.CreateInstance(this.GetType());
//我们取得新的类型实例的字段数组。
FieldInfo[] fields = newObject.GetType().GetFields();
int i = 0;
foreach (FieldInfo fi in this.GetType().GetFields())
{
//我们判断字段是否支持ICloneable接口。
Type ICloneType = fi.FieldType.GetInterface("ICloneable", true);
if (ICloneType != null)
{
//取得对象的Icloneable接口。
ICloneable IClone = (ICloneable)fi.GetValue(this);
//我们使用克隆方法给字段设定新值。
fields[i].SetValue(newObject, IClone.Clone());
}
else
{
// 如果该字段部支持Icloneable接口,直接设置即可。
fields[i].SetValue(newObject, fi.GetValue(this));
}
//现在我们检查该对象是否支持IEnumerable接口,如果支持,
//我们还需要枚举其所有项并检查他们是否支持IList 或 IDictionary 接口。
Type IEnumerableType = fi.FieldType.GetInterface("IEnumerable", true);
if (IEnumerableType != null)
{
//取得该字段的IEnumerable接口
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);
Type IListType = fields[i].FieldType.GetInterface("IList", true);
Type IDicType = fields[i].FieldType.GetInterface("IDictionary", true);
int j = 0;
if (IListType != null)
{
//取得IList接口。
IList list = (IList)fields[i].GetValue(newObject);
foreach (object obj in IEnum)
{
//查看当前项是否支持支持ICloneable 接口。
ICloneType = obj.GetType().GetInterface("ICloneable", true);
if (ICloneType != null)
{
//如果支持ICloneable 接口,
//我们用它李设置列表中的对象的克隆
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
//注意:如果列表中的项不支持ICloneable接口,那么
//在克隆列表的项将与原列表对应项相同
//(只要该类型是引用类型)
j++;
}
}
else if (IDicType != null)
{
//取得IDictionary 接口
IDictionary dic = (IDictionary)fields[i].GetValue(newObject);
j = 0;
foreach (DictionaryEntry de in IEnum)
{
//查看当前项是否支持支持ICloneable 接口。
ICloneType = de.Value.GetType().
GetInterface("ICloneable", true);
if (ICloneType != null)
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
i++;
}
return newObject;
}
}
如何使用
让你的类支持Icloneable接口所要做的就是,将你的类继承自如下所述的BaseObject类:

public class MyClass : BaseObject
{
public string myStr ="test";
public int id;
}
public class MyContainer : BaseObject
{
public string name = "test2";
public MyClass[] myArray= new MyClass[5];
public class MyContainer()
{
for(int i=0 ; i<5 ; i++)
{
this.myArray[I] = new MyClass();
}
}
}

现在在Main方法中加入如下代码:

static void Main(string[] args)
{
MyContainer con1 = new MyContainer();
MyContainer con2 = (MyContainer)con1.Clone();
con2.myArray[0].id = 5;
}

19.XML属性文件解析
/*
using System.Xml;
using System.IO;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
throws ParserConfigurationException, SAXException, IOException {
*/
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
Document doc=db.parse(%%1); //"mybook.xml"
doc.normalize();
NodeList nl=doc.getElementsByTagName("book");
for(int i=0;i<nl.getLength();i++){
Element e=(Element)nl.item(i);
String title=e.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();
String author=e.getElementsByTagName("author").item(0).getFirstChild().getNodeValue();
String price=e.getElementsByTagName("price").item(0).getFirstChild().getNodeValue();
System.out.println("title:"+title);
System.out.println("author:"+author);
System.out.println("price:"+price);
}
<!--
读取XML配置文件
/*
using System.Xml;
using System.IO;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
*/
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
db = dbf.newDocumentBuilder();
Document doc;
doc = db.parse("config.xml");
doc.normalize();
NodeList nl = doc.getElementsByTagName("book");
for (int i = 0; i < nl.getLength(); i++) {
Element e = (Element) nl.item(i);
String strurl = e.getElementsByTagName("dbsource").item(0)
.getFirstChild().getNodeValue();
String username;
if (e.getElementsByTagName("username").item(0).getFirstChild() == null) {
username = "";
} else {
username = e.getElementsByTagName("username").item(0)
.getFirstChild().getNodeValue();
}
String password;
if (e.getElementsByTagName("username").item(0).getFirstChild() == null) {
password = "";
} else {
password = e.getElementsByTagName("password").item(0)
.getFirstChild().getNodeValue();
}
// strurl
// username
// password
}
} catch (ParserConfigurationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SAXException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
-->

20.XML属性文件构造
/*
using System.Xml;
using System.IO;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
throws ParserConfigurationException, SAXException, IOException {
*/
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
Document doc=db.parse(%%1); //"mybook.xml"
doc.normalize();
NodeList nl=doc.getElementsByTagName("book");
for(int i=0;i<nl.getLength();i++){
Element e=(Element)nl.item(i);
String title=e.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();
String author=e.getElementsByTagName("author").item(0).getFirstChild().getNodeValue();
String price=e.getElementsByTagName("price").item(0).getFirstChild().getNodeValue();
System.out.println("title:"+title);
System.out.println("author:"+author);
System.out.println("price:"+price);
}

21.XML文件节点遍历操作
/*
using System.Xml;
private XmlDocument doc = new XmlDocument();
private XmlNode attrColl;
*/
private XmlNode SelectedNodes( XmlNode attrColl)
{
XmlNode childNode;
XmlNode brotherNode;
bool pd;


try
{

if( attrColl.HasChildNodes ==true)
{
childNode = SelectedNodes(attrColl.FirstChild);
return (childNode);
}
else
{

MessageBox.Show(attrColl.Name);
if( attrColl.NextSibling != null)
{

attrColl = attrColl.NextSibling;

}
else
{

while(attrColl.NextSibling == null)
{
MessageBox.Show(attrColl.ParentNode.Name.ToString());
attrColl = attrColl.ParentNode;

}
attrColl = attrColl.NextSibling;
// MessageBox.Show("PPP");

}

return ( SelectedNodes( attrColl));

}
}
catch
{
}
return attrColl;
}

// XmlDocument doc = new XmlDocument();
doc.Load("http://localhost/data.xml");
//Create an attribute collection.

// XmlNode attrColl = doc.DocumentElement.SelectSingleNode("//book");
attrColl = doc.DocumentElement.SelectSingleNode("//book/*");
this.SelectedNodes(attrColl);

22.XML文件节点遍历查找
/*
using System.Xml;
private XmlDocument doc = new XmlDocument();
private XmlNode attrColl;
*/
private XmlNode SelectedNodes( XmlNode attrColl)
{
XmlNode childNode;
XmlNode brotherNode;
bool pd;


try
{

if( attrColl.HasChildNodes ==true)
{
childNode = SelectedNodes(attrColl.FirstChild);
return (childNode);
}
else
{

MessageBox.Show(attrColl.Name);
if( attrColl.NextSibling != null)
{

attrColl = attrColl.NextSibling;

}
else
{

while(attrColl.NextSibling == null)
{
MessageBox.Show(attrColl.ParentNode.Name.ToString());
attrColl = attrColl.ParentNode;

}
attrColl = attrColl.NextSibling;
// MessageBox.Show("PPP");

}

return ( SelectedNodes( attrColl));

}
}
catch
{
}
return attrColl;
}

// XmlDocument doc = new XmlDocument();
doc.Load("http://localhost/data.xml");
//Create an attribute collection.

// XmlNode attrColl = doc.DocumentElement.SelectSingleNode("//book");
attrColl = doc.DocumentElement.SelectSingleNode("//book/*");
this.SelectedNodes(attrColl);

23.Remoting

using System;

namespace Remotable
{

public class RemotableType : MarshalByRefObject
{
private string _internalString = "This is the RemotableType.";
public string StringMethod()
{
return _internalString;
}
}

}

using System;
using System.Runtime.Remoting;


namespace RemotingFirst
{

public class Listener
{
public static void Main()
{
RemotingConfiguration.Configure("Listener.exe.config");
Console.WriteLine("Listening for requests. Press Enter to exit");
Console.ReadLine();
}
}

}


using System;
using System.Runtime.Remoting;


namespace Client
{


public class Client
{

public static void Main()
{
RemotingConfiguration.Configure("Client.exe.config");
Remotable.RemotableType remoteObject = new Remotable.RemotableType();
Console.WriteLine(remoteObject.StringMethod());
}
}

}


Listener.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="Remotable.RemotableType, RemotableType"
objectUri="RemotableType.rem"
/>
</service>
<channels>
<channel ref="http" port="8989"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>

25.
实只要用到Socket联接,基本上就得使用Thread,是交叉使用的。
C#封装的Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。
在C#里面能找到的最底层的操作也就是socket了,概念不做解释。
程序模型如下:
WinForm程序 : 启动端口侦听;监视Socket联接情况;定期关闭不活动的联接;
Listener:处理Socket的Accept函数,侦听新链接,建立新Thread来处理这些联接(Connection)。
Connection:处理具体的每一个联接的会话。

1:WinForm如何启动一个新的线程来启动Listener:
//start the server
private void btn_startServer_Click(object sender, EventArgs e)
{
//this.btn_startServer.Enabled = false;
Thread _createServer = new Thread(new ThreadStart(WaitForConnect));
_createServer.Start();
}
//wait all connections
private void WaitForConnect()
{
SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));
listener.StartListening();
}
因为侦听联接是一个循环等待的函数,所以不可能在WinForm的线程里面直接执行,不然Winform也就是无法继续任何操作了,所以才指定一个新的线程来执行这个函数,启动侦听循环。
这一个新的线程是比较简单的,基本上没有启动的参数,直接指定处理函数就可以了。
2:Listener如何启动循环侦听,并且启动新的带有参数的线程来处理Socket联接会话。
先看如何建立侦听:(StartListening函数)
IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(20);//20 trucks

// Start listening for connections.
while (true)
{
// here will be suspended while waiting for a new connection.
Socket connection = listener.Accept();
Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection
……
}
}
/*
基本步骤比较简单:
建立本机的IPEndPoint对象,表示以本机为服务器,在指定端口侦听;
然后绑定到一个侦听Socket上;
进入while循环,等待新的联接;
如果有新的联接,那么建立新的socket来对应这个联接的会话。
值得注意的就是这一句联接代码:listener.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。

新的联接Socket建立了(Accept之后),对于这些新的socket该怎么办呢?他们依然是一个循环等待,所以依然需要建立新的Thread给这些Socket去处理会话(接收/发送消息),而这个Thread就要接收参数了。
Thread本身是不能接收参数的,为了让它可以接收参数,可以采用定义新类,添加参数作为属性的方法来解决。
因为每一个Socket是一个Connection周期,所以我定义了这么一个类public class Connection。这个类至少有这样一个构造函数public Connection(Socket socket); 之所以这么做,就是为了把Socket参数传给这个Connection对象,然后好让Listener启动这个Thread的时候,Thread可以知道他正在处理哪一个Socket。
具体处理的方法:(在Listener的StartListening函数,ocket connection = listener.Accept();之后)
Connection gpsCn = new Connection(connection);
//each socket will be wait for data. keep the connection.
Thread thread = new Thread(new ThreadStart(gpsCn.WaitForSendData));
thread.Name = connection.RemoteEndPoint.ToString();
thread.Start();
如此一来,这个新的socket在Accept之后就在新的Thread中运行了。
3:Connection的会话处理
建立了新的Connection(也就是socket),远程就可以和这个socket进行会话了,无非就是send和receive。
现在先看看怎么写的这个线程运行的Connection. WaitForSendData函数
*/
while (true)
{
bytes = new byte[1024];
string data = "";
//systm will be waiting the msg of receive envet. like Accept();
//here will be suspended while waiting for socket income msg.
int bytesRec = this._connection.Receive(bytes);
_lastConnectTime = DateTime.Now;
if (bytesRec == 0)//close envent
{
Logger.Log("Close Connection", _connection.RemoteEndPoint.ToString());
break;
}
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
//…….handle your data.
}
/*
可以看到这个处理的基本步骤如下:
执行Receive函数,接收远程socket发送的信息;
把信息从字节转换到string;
处理该信息,然后进入下一个循环,继续等待socket发送新的信息。
值得注意的有几个:
1:Receive函数。这个函数和Listener的Accept函数类似。在这个地方等待执行,如果没有新的消息,这个函数就不会执行下一句,一直等待。
2:接收的是字节流,需要转化成字符串
3:判断远程关闭联接的方式
4:如果对方的消息非常大,还得循环接收这个data。
4:如何管理这些联接(thread)
通过上边的程序,基本上可以建立一个侦听,并且处理联接会话。但是如何管理这些thread呢?不然大量产生thread可是一个灾难。
管理的方法比较简单,在Listener里面我定义了一个静态的哈希表(static public Hashtable Connections=new Hashtable();),存储Connection实例和它对应的Thread实例。而connection中也加入了一个最后联接时间的定义(private DateTime _lastConnectTime;)。在新链接建立的时候(Listener的Accept()之后)就把Connection实例和Thread实例存到哈希表中;在Connection的Receive的时候修改最后联接时间。这样我们就可以知道该Connection在哪里,并且会话是否活跃。
然后在Winform程序里头可以管理这些会话了,设置设置超时。
在网络环境下,我们最感兴趣的两个命名空间是System.Net和 System.Net.Sockets。System.Net命名空间通常与较高程的操作有关,例如download或upload,试用HTTP和其他协议进行Web请求等等,而System.Net.Sockets命名空间所包含的类通常与较低程的操作有关。如果要直接使用Sockets或者 TCP/IP之类的协议,这个命名空间的类是非常有用的。

  在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如 Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。

  其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。

  可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据。

  针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发 windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。

  在使用之前,你需要首先创建Socket对象的实例,这可以通过Socket类的构造方法来实现:

public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);

  其中,addressFamily 参数指定 Socket 使用的寻址方案,socketType 参数指定 Socket 的类型,protocolType 参数指定 Socket 使用的协议。

  下面的示例语句创建一个 Socket,它可用于在基于 TCP/IP 的网络(如 Internet)上通讯。

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  若要使用 UDP 而不是 TCP,需要更改协议类型,如下面的示例所示:

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

  一旦创建 Socket,在客户端,你将可以通过Connect方法连接到指定的服务器,并通过Send/SendTo方法向远程服务器发送数据,而后可以通过 Receive/ReceiveFrom从服务端接收数据;而在服务器端,你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联,并通过Listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用Accept完成连接的操作,创建新的Socket以处理传入的连接请求。使用完 Socket 后,记住使用 Shutdown 方法禁用 Socket,并使用 Close 方法关闭 Socket。

  可以看出,以上许多方法包含EndPoint类型的参数,在Internet中,TCP/IP 使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点,在 .NET 框架中正是由 EndPoint 类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。.Net同时也为每个受支持的地址族定义了 EndPoint 的子代;对于 IP 地址族,该类为 IPEndPoint。IPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机IP地址和端口号,IPEndPoint 类形成到服务的连接点。

  用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址,System.Net命名空间中有两种类可以得到IP地址实例:

  IPAddress类:IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例:

IPAddress myIP = IPAddress.Parse("192.168.0.1");

  Dns 类:向使用 TCP/IP Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS 服务器以将用户友好的域名(如"host.mydomain.com")映射到数字形式的 Internet 地址(如 192.168.0.1)。Resolve方法 返回一个 IPHostEnty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例,该实例包含服务器 host.mydomain.com 的 IP 地址。

IPHostEntry ipHostInfo = Dns.Resolve("host.mydomain.com ");
IPAddress ipAddress = ipHostInfo.AddressList[0];

  你也可以使用GetHostName方法得到IPHostEntry实例:

IPHosntEntry hostInfo=Dns.GetHostByName("host.mydomain.com ")

  在使用以上方法时,你将可能需要处理以下几种异常:

  SocketException异常:访问Socket时操作系统发生错误引发

  ArgumentNullException异常:参数为空引用引发

  ObjectDisposedException异常:Socket已经关闭引发

  在掌握上面得知识后,下面的代码将该服务器主机( host.mydomain.com的 IP 地址与端口号组合,以便为连接创建远程终结点:

IPEndPoint ipe = new IPEndPoint(ipAddress,11000);

  确定了远程设备的地址并选择了用于连接的端口后,应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 IPEndPoint 实例与远程设备连接,并捕获可能引发的异常:
*/

try
{
temp.Connect(ipe);//尝试连接
}
//处理参数为空引用异常
catch(ArgumentNullException ae)
{
Console.WriteLine("ArgumentNullException : {0}", ae.ToString());
}
//处理操作系统异常
catch(SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
/*
  需要知道的是:Socket 类支持两种基本模式:同步和异步。其区别在于:在同步模式中,对执行网络操作的函数(如 Send 和 Receive)的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中,这些调用立即返回。


综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识,下面的程序是一个简单的Socket通讯实例,client向server发送一段测试字符串,server接收并显示出来,给予client成功相应。
*/
//client端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace socketsample
{
 class Class1
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    c.Connect(ipe);
    string sendStr = "hello!This is a socket test";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    c.Send(bs, bs.Length, 0);
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = c.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    c.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}
//server端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Project1
{
 class Class2
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    s.Bind(ipe);
    s.Listen(0);
    Socket temp = s.Accept();
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    string sendStr = "Ok!Sucess!";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    temp.Send(bs, bs.Length, 0);
    temp.Shutdown(SocketShutdown.Both);
    temp.Close();
    s.Shutdown(SocketShutdown.Both);
    s.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}

23.多线程端口监听
本人已经用C#实现了多个客户端连接服务端的问题,但我还想限制客户端的连接数。例如我希望同时连接到服务端的数目为2,若第三个发起连接请求时会失败。
本人已基本想出解决限制客户端的连接数的方法,但是出现一个问题就是明明我是设置只允许连接N个,却可以连接N+1个,但第N+2个时就会失败,我没查出原因。
我的代码如下:
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TCPSERVER
{
public partial class FrmServer : Form
{
private Socket m_ServerListener = null;
private ClientInformationCls[] m_clientList;
delegate void SetTextCallback(string strText);
private const int MAX_CLIENT = 1; //client connnecting max number

public FrmServer()
{
InitializeComponent();
}

private static IPAddress GetServerIP()
{

IPHostEntry ieh = Dns.GetHostEntry(Dns.GetHostName());

return ieh.AddressList[0];

}

private void BeginListen()
{
int intPort =8000;

m_clientList=new ClientInformationCls[ MAX_CLIENT ];

IPAddress ServerIp = GetServerIP();

IPEndPoint iep = new IPEndPoint(ServerIp, intPort);
m_ServerListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ServerListener.Bind(iep);
m_ServerListener.Listen(1);
}

private void btnBeginListen_Click(object sender, EventArgs e)
{


try
{
BeginListen();
lstServerStatus.Items.Add("Server is starting listening....");

InitClientList();

Thread acceptThread = new Thread(new ThreadStart(AcceptClientThread));
acceptThread.Start();


}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}

private void AcceptClientThread()
{
int intClientIndex;

Thread.CurrentThread.IsBackground = true;

try
{
while (true)
{
intClientIndex = GetFreeClient();
if (intClientIndex != -1)
{
m_clientList[intClientIndex].IsIdle = false;
Socket clientSocket = m_ServerListener.Accept();
IPEndPoint remoEP = (IPEndPoint)clientSocket.RemoteEndPoint;

m_clientList[intClientIndex].ClientIP = remoEP.Address.ToString();
m_clientList[intClientIndex].ClientSocket = clientSocket;
SetText("connecting from " + m_clientList[intClientIndex].ClientIP);

Thread DealingThread = new Thread(new ParameterizedThreadStart(RcvSndThread));

DealingThread.Start(m_clientList[intClientIndex]);

}
}
}

catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}

}

private void RcvSndThread(object obj)
{
Thread.CurrentThread.IsBackground = true;
ClientInformationCls clientTmp = (ClientInformationCls)obj;

byte[] buffer = new byte[1024];
int intRcvCount;

try
{
while (clientTmp.ClientSocket.Connected == true)
{
intRcvCount = clientTmp.ClientSocket.Receive(buffer);
SetText(Encoding.Default.GetString(buffer, 0, intRcvCount));

}
}

catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}

catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}


}

private void InitClientList()
{
int i = 0;
for (i=0; i <= m_clientList.Length-1; i++)
{
m_clientList[i] = new ClientInformationCls();
m_clientList[i].ClientHostName="";
m_clientList[i].ClientIP = "";
m_clientList[i].Index=i;
m_clientList[i].IsIdle = true;
m_clientList[i].ClientSocket = null;
}
}

private int GetFreeClient()
{
int i = 0;

for (i = 0; i <= m_clientList.Length - 1; i++)
{
if (m_clientList[i] == null) return -1;

if (m_clientList[i].IsIdle == true)
{
return i;
}
}
return -1;
}

private void SetText(string strText)
{
if (this.lstServerStatus.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { strText });
}
else
{
this.lstServerStatus.Items.Add(strText);
}
}

}
}
其中 ClientInformationCls是本人自定义的类,一个保存客户端SOCKET的连接信息,其中有个IsIdle属性用来记录该SOCKET是否可用
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace TCPSERVER
{
class ClientInformationCls
{

private int m_intClientIndex; //client's index
private string m_strClientIP;
private string m_strClientHostName;
private bool m_blnIsIdle;
private Socket m_clientSocket;
public int Index
{
get{return m_intClientIndex;}
set{m_intClientIndex=value;}
}

public string ClientIP
{
get { return m_strClientIP; }
set { m_strClientIP = value; }
}

public string ClientHostName
{
get { return m_strClientHostName; }
set { m_strClientHostName = value; }
}

public bool IsIdle
{
get { return m_blnIsIdle; }
set { m_blnIsIdle = value; }
}
public Socket ClientSocket
{
get { return m_clientSocket; }
set { m_clientSocket = value; }
}
}
}

我在AcceptClientThread函数中调用了
intClientIndex = GetFreeClient();
如果intClientIndex=-1的话表示不能在允许其他的客户端连接,这样就不会创建新的线程了,
现在我的问题是我明明创建了数组 m_clientList=new ClientInformationCls[ MAX_CLIENT ];
而MAX_CLIENT初始化时已经设置为1了,也就是说服务端最大的连接数为MAX_CLIENT=1,
而我测试的时候,服务端最大的连接数为MAX_CLIENT+1了,请高手帮忙看看

24.多线程端口扫描
/*
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
*/
//该处放的是程序要用到的公共变量
public string scanHost = Dns.GetHostName(); //默认当前本机IP
public Int32 tport = 0; //当前连接端口编号
public Int32 connState = 0; //扫描状态
public int portSum = 0 ; //端口总计
public bool endThread = false; //结束状态
public AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);
*/
private void Startscan(Object state)
{
Int32 port = (Int32) state;
string tMsg = "";
string getData = "";
int lindex = 0;
int eindex = 0;
connState++; //判断线程数目
if(endThread==true)
{
if(connState==((Int32)eNum.Value-(Int32)sNum.Value))
{
cmdExec.Text = "&Scan";
logList.Items.Add ("扫描完毕!");
}
else
{
cmdExec.Text = "&Stop";
logList.Items.Add ("正在停止对"+port.ToString()+"端口的扫描线程");
}
logList.Items.Add("结束线程:"+port.ToString());
asyncOpsAreDone.Close();
}
else
{
try
{
TcpClient tcp = new TcpClient();
tcp.Connect(scanHost,port);
//该处如果建立连接错误的话,将不执行下面的代码..
portSum ++;
lindex = portList.Items.Add(port.ToString() + "端口开放",false);
portList.SelectedIndex=lindex;
Stream sm = tcp.GetStream();
sm.Write(Encoding.Default.GetBytes(tMsg.ToCharArray()),0,tMsg.Length);
StreamReader sr = new StreamReader(tcp.GetStream(),Encoding.Default);
getData = sr.ReadLine();
if(lindex!=0&&getData.Length!=0)
{
tMsg = " +-" + port.ToString() + "端口数据:"+getData.ToString();
eindex = portList.Items.Add(tMsg); //插入一条信息记录
portList.Items.Insert(lindex+1,tMsg);
portList.Items.RemoveAt(eindex);
}
sr.Close();
sm.Close();
tcp.Close();
}
catch
{
//显示坏死的端口
if(showdie.Checked==true)
{
portList.Items.Add(port.ToString()+"端口无法连接,回传数据为空");
}
}
finally
{
Thread.Sleep(0);
logList.Items.Add("结束线程:"+port.ToString());
asyncOpsAreDone.Close();
statusBar1.Text = "端口总计:"+portSum.ToString() ;
if(connState==((Int32)eNum.Value-(Int32)sNum.Value))
{
cmdExec.Text = "&Scan";
}
}
Int32 startPort = (Int32)sNum.Value;
Int32 endPort = (Int32)eNum.Value;
if(txtHostname.Text.Length==0)
{
MessageBox.Show("请输入一个主机的名称吧!","系统提示");
txtHostname.Text = scanHost.ToString();
txtHostname.Focus();
return;
}
if(startPort>endPort)
{
MessageBox.Show("错误,起始端口必须要小于结束的端口!","系统提示");
startPort = endPort-1;
sNum.Text = startPort.ToString();
sNum.Focus();
return ;
}

if(cmdExec.Text=="&Scan")
{
endThread= false;
cmdExec.Text= "&Stop";
}
else
{
endThread= true;
cmdExec.Text= "&Scan";
}
}
///
if(endThread!=true)
{
connState = 0;
portSum = 0;
scanHost = txtHostname.Text;
try
{
IPAddress ipaddr =(IPAddress)Dns.Resolve(scanHost).AddressList.GetValue(0);
txtHostname.Text = ipaddr.ToString();
}
catch
{
txtHostname.Focus();
MessageBox.Show("请输入正确的主机地址,该地址DNS无法解析","系统提示");
return ;
}
for (Int32 threadNum = startPort; threadNum <=endPort; threadNum++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Startscan),threadNum);
//扫描端口:" + threadNum.ToString()
}

25.发送带附件的邮件
//using System.Net.Mail;
MailAddress EmailFrom =new MailAddress(%%1); //"Emaster@126.com"
MailAddress EmailTo = new MailAddress(%%2); //收件人地址
MailMessage Email = new MailMessage(EmailFrom, EmailTo);
Email.Priority = MailPriority.High;

Email.Subject = "大众计算机学习网发送给您的邮件";
Email.Body = "邮件内容在附件里面,请自行打开!";
//添加抄送电子邮件
Email.CC.Add("这里就是你发送邮件的目标拉,填写抄送收件人的邮件地址");

string file = Server.MapPath("EmailAttachment//") + "Data.rar";//附件路径
Attachment data = new Attachment(file,System.Net.Mime.MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
System.Net.Mime.ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
Email.Attachments.Add(data);

SmtpClient Client = new SmtpClient("smtp.126.com");

//验证 (Credentials 凭证)
Client.Credentials = new System.Net.NetworkCredential("你邮箱的地址", "你登陆邮箱的密码");

//处理待发的电子邮件的方法 (Delivery 发送,传输)
Client.DeliveryMethod = SmtpDeliveryMethod.Network;
try
{
Client.Send(Email);
Response.Write("已发送成功啦");
}
catch (SmtpFailedRecipientsException ex)
{
for (int i = 0; i < ex.InnerExceptions.Length; i++)
{
SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Response.Write("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000);
Client.Send(Email );
}
else
{
Response.Write("Failed to deliver message to {0}"+ex.FailedRecipient[i].ToString().Trim()+"
");
}
}

26.接收带附件的邮件
/*
using System.Text;
using System.IO;
using Email.POP3;
*/
namespace TestPOP3
{
class example
{
[STAThread]
static void Main(string[] args)
{
//我测试的时候用的是163的邮箱,163的免费POP邮件服务器是pop.163.com。而163官方给出的是
//pop.126.com在这里不能用,原因是这个邮件服务器是有SSL加密的,GMAIL我也测试了也不能用都是这个原因
POP3 objPOP3 = new POP3("pop.163.com", 110, "用户名", "密码");
Console.WriteLine(objPOP3.Connect() ? "Connected" : "Can't connect");
try
{
if (objPOP3.IsAPOPSupported)
{
Console.WriteLine(objPOP3.SecureLogin() ? "Secure Logged in" : "Can't login");
}
else
{
Console.WriteLine(objPOP3.Login() ? "Logged in" : "Can't login");
}
objPOP3.QueryServer();
Console.WriteLine("Emails count: " + objPOP3.TotalMailCount);
//以下的FOR循环是显示出所有收件箱里面的邮件信息
for (int i = 1; i <= objPOP3.TotalMailCount; i++)
{
EmailMessage objEmail = objPOP3.GetMessage(i, false); // use true to get headers only
Console.WriteLine("NEW MESSAGE:------------------");
Console.WriteLine("FROM: " + objEmail.From);
Console.WriteLine("TO: " + objEmail.To);
Console.WriteLine("CC: " + objEmail.Cc);
Console.WriteLine("SUBJECT: " + objEmail.Subject);
Console.WriteLine("DATE: " + objEmail.Date);
Console.WriteLine("CONTENT-TYPE: " + objEmail.ContentType);
Console.WriteLine("CHARSET: " + objEmail.Charset);
Console.WriteLine("MESSAGE-ID: " + objEmail.GetCustomHeader("Message-ID"));
Console.WriteLine("MESSAGE SIZE: " + objEmail.Size);
if (objEmail.IsAnyAttachments)
{
for (int a = 0; a < objEmail.Attachments.Count; a++)
{
//调用邮件附件的方法
processAttachment((Attachment)objEmail.Attachments[a], 1);
}
}
else
{
Console.WriteLine("BODY: " + Encoding.Default.GetString(Convert.FromBase64String(objEmail.Body)));
}
//下面注册掉的代码是删除该邮件
//objPOP3.DeleteMessage(i);

}
objPOP3.Close();
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
objPOP3.Close();
return;
}

}

static void processAttachment(Attachment att, int nesting)
{
for(int i = 0; i < nesting * 2; i++) Console.Write("-");

//以下注释掉的代码可以打开,以下都是关于邮件附件的相关信息,因为我只需要得到附件的文件信息^_^

//Console.WriteLine("ATT: ");
//Console.WriteLine("ContentTransferEncoding: " + att.ContentTransferEncoding);
//Console.WriteLine("ContentType: " + att.ContentType);
//Console.WriteLine("EstimatedSize: " + att.EstimatedSize);
//Console.WriteLine("FileName: " + att.FileName);
//processBody("HtmlBody", att.HtmlBody);
//processBody("TextBody", att.TextBody);
//Console.WriteLine("IsAnyAttachments: " + att.IsAnyAttachments);
//Console.WriteLine("IsFileAttachment: " + att.IsFileAttachment);
if (att.IsAnyAttachments)
{
for (int a = 0; a < att.Attachments.Count; a++)
{
processAttachment((Attachment)att.Attachments[a], nesting * 2);
}
}
if(att.IsFileAttachment)
{
//这里说一下在保存邮件附件之前必须"c:/pop3"该文件夹是存在的,否则是保存不了的
att.Save(@"c:/pop3" + att.FileName);
Console.WriteLine("附件保存成功!附件名称为:" + att.FileName);
}
}

static void processBody(string bodytype, string body)
{
if (body == null)
{
Console.WriteLine(bodytype + ": null");
return;
}
if (body.Length > 1000)
{
Console.WriteLine(bodytype + ": " + body.Substring(0, 1000) + "...");
}
else
{
Console.WriteLine(bodytype + ": " + body);
}
}
}
}


27.Ping
//using System.Net;
NetworkInformation.Ping p = new NetworkInformation.Ping();
NetworkInformation.PingOptions options = new NetworkInformation.PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
//Wait seconds for a reply.
int timeout = 4000
NetworkInformation.PingReply reply = p.Send(%%1, timeout, buffer, options);
%%2=reply.Status;

28.调用Web Service
//using System.Net;
localhost.Service test = new localhost.Service();
localhost.AuthenHeader authenHeader = new localhost.AuthenHeader();
authenHeader.Authen = "sindyware";
test.authenHeader = authenHeader;
TextBox1.Text = test.Conversion("df","sdafa","dsfa","asdfa","adfs","asdfa");

29.HTTP代理服务器
//Proxy.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace WebProxy
{
class Proxy
{
public Proxy(Socket socket)
{
//
// TODO: 在此处添加构造函数逻辑
//
this.clientSocket = socket;
}

Socket clientSocket;
Byte[] read = new byte[1024];
//定义一个空间,存储来自客户端请求数据包
Byte[] Buffer = null;
Encoding ASCII = Encoding.ASCII;
//设定编码
Byte[] RecvBytes = new Byte[4096];
//定义一个空间,存储Web服务器返回的数据

//Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

public void Run()
{
string clientmessage = "";
//存放来自客户端的HTTP请求字符串
string URL = "";
//存放解析出地址请求信息
int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0)
{
return;
}

int index1 = clientmessage.IndexOf(' ');
int index2 = clientmessage.IndexOf(' ', index1 + 1);
if ((index1 == -1) || (index2 == -1))
{
throw new IOException();
}
string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
int index3 = part1.IndexOf('/', index1 + 8);
int index4 = part1.IndexOf(' ', index1 + 8);
int index5 = index4 - index3;
URL = part1.Substring(index1 + 4, (part1.Length - index5) - 8);

try
{
IPHostEntry IPHost = Dns.Resolve(URL);
Console.WriteLine("远程主机名: " + IPHost.HostName);
string[] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList;
Console.WriteLine("Web服务器IP地址:" + address[0]);
//解析出要访问的服务器地址
IPEndPoint ipEndpoint = new IPEndPoint(address[0], 80);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建连接Web服务器端的Socket对象
IPsocket.Connect(ipEndpoint);
//Socket连Web接服务器
if (IPsocket.Connected)
Console.WriteLine("Socket 正确连接!");
string GET = clientmessage;
Byte[] ByteGet = ASCII.GetBytes(GET);
IPsocket.Send(ByteGet, ByteGet.Length, 0);
//代理访问软件对服务器端传送HTTP请求命令
Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
//代理访问软件接收来自Web服务器端的反馈信息
Console.WriteLine("接收字节数:" + rBytes.ToString());
String strRetPage = null;
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
while (rBytes > 0)
{
rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
}
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
SendMessage(clientSocket, strRetPage);
//代理服务软件往客户端传送接收到的信息
}
catch (Exception exc2)
{
Console.WriteLine(exc2.ToString());
}
}
//接收客户端的HTTP请求数据
private int ReadMessage(byte[] ByteArray, ref Socket s, ref String clientmessage)
{
int bytes = s.Receive(ByteArray, 1024, 0);
string messagefromclient = Encoding.ASCII.GetString(ByteArray);
clientmessage = (String)messagefromclient;
return bytes;
}
//传送从Web服务器反馈的数据到客户端
private void SendMessage(Socket s, string message)
{
Buffer = new Byte[message.Length + 1];
int length = ASCII.GetBytes(message, 0, message.Length, Buffer, 0);
Console.WriteLine("传送字节数:" + length.ToString());
s.Send(Buffer, length, 0);
}

}
}

//Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using WebProxy;

namespace WebProxy
{
class Program
{
static void Main(string[] args)
{
const int port = 8000;
//定义端口号
TcpListener tcplistener = new TcpListener(port);
Console.WriteLine("侦听IP: " + tcplistener.Server.ToString());
Console.WriteLine("侦听端口号: " + port.ToString());
tcplistener.Start();
//侦听端口号
while (true)
{
Socket socket = tcplistener.AcceptSocket();
//并获取传送和接收数据的Scoket实例
Proxy proxy = new Proxy(socket);
//Proxy类实例化
Thread thread = new Thread(new ThreadStart(proxy.Run));
//创建线程
thread.Start();
//启动线程
}
}
}
}

C#实现HTTP代理服务程序的补充

用文中处理中文页面会出产生乱码,问题就在于Encoding ASCII = Encoding.ASCII一句。服务器返回的中文编码,按ASCII处理之后返给浏览器必然是乱码。那么将返给浏览器信息处的ASCII.GetBytes换成Encoding.Default.GetString是否就能正常显示中文呢?似乎不行,替换了之后产生转换缓冲区溢出的异常。还是编码的问题,message.Length时一个中文的长度是1,而GetBytes的时候一个中文却是两位。下边是我修改过的SendMessage函数。
private void SendMessage ( Socket s , string message )
{  
Buffer=Encoding.Default.GetBytes( message) ;
  Console.WriteLine ( "传送字节数:" + Buffer.Length.ToString ( ) ) ;  
s.Send ( Buffer , Buffer.Length , 0 ) ; }
修改过之后显示中文页面时似乎就正常了:)

将收到的byte转换成string的方法是不行的。因为接收到的byte流可能是两种编码,Http头部ASCII码,后面的网页实际内容可能是UTF8,GB2312之类。所以按文中给的方法将byte转成string,再将string转回byte,就会产生乱码和网页打不开的现象。

我想出的解决办法是,将每次收到byue数组放到ArrayList当中,当全部收完时再将ArrayList中的各个Byte数组拼成一个大的Byte数组,发给浏览器。

这样虽然不会乱码了,但肯定不是一个好方法。做出来的所谓“代理服务器”就是个娱乐级,自己搭个局域网玩玩还行。拿到真实的网络环境下的话……基本没什么用。

30.创建启动线程
//using System.Threading;
private static Thread thThread;
private static void Listen()
{
}
thThread= new Thread(new ThreadStart(Listen));
thThread.Start();

31.线程挂起唤醒
//using System.Threading;
thThread.Suspend();
thThread.Resume();

32.线程插入终止
//using System.Threading;
thThread.Join();
thThread.Abort();

33.HTTP多线程下载
/*
using System.Net;//网络功能
using System.IO;//流支持
using System.Threading ;//线程支持
private bool[] threadw; //每个线程结束标志
private string[] filenamew;//每个线程接收文件的文件名
private int[] filestartw;//每个线程接收文件的起始位置
private int[] filesizew;//每个线程接收文件的大小
private string strurl;//接受文件的URL
private bool hb;//文件合并标志
private int thread;//进程数
*/
public class HttpFile
{
 public Form1 formm;
 public int threadh;//线程代号
 public string filename;//文件名
 public string strUrl;//接收文件的URL
 public FileStream fs;
 public HttpWebRequest request;
 public System.IO.Stream ns;
 public byte[] nbytes;//接收缓冲区
 public int nreadsize;//接收字节数
 public HttpFile(Form1 form,int thread)//构造方法
 {
  formm=form;
  threadh=thread;
 }
 ~HttpFile()//析构方法
 {
  formm.Dispose ();
 }
 public void receive()//接收线程
 {
  filename=formm.filenamew[threadh];
  strUrl=formm.strurl;
  ns=null;
  nbytes= new byte[512];
  nreadsize=0;
  formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"开始接收");
  fs=new FileStream (filename,System.IO.FileMode.Create);
  try
  {
   request=(HttpWebRequest)HttpWebRequest.Create (strUrl);
   //接收的起始位置及接收的长度
   request.AddRange(formm.filestartw [threadh],
   formm.filestartw [threadh]+formm.filesizew [threadh]);
   ns=request.GetResponse ().GetResponseStream ();//获得接收流
   nreadsize=ns.Read (nbytes,0,512);
   while (nreadsize>0)
   {
    fs.Write (nbytes,0,nreadsize);
    nreadsize=ns.Read (nbytes,0,512);
    formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"正在接收");
   }
   fs.Close();
   ns.Close ();
  }
  catch (Exception er)
  {
   MessageBox.Show (er.Message );
   fs.Close();
  }
  formm.listBox1 .Items.Add ("进程"+threadh.ToString ()+"接收完毕!");
  formm.threadw[threadh]=true;
 }
}
public void hbfile()
{
 while (true)//等待
 {
  hb=true;
  for (int i=0;i<thread;i++)
  {
   if (threadw[i]==false)//有未结束线程,等待
   {
    hb=false;
    Thread.Sleep (100);
    break;
   }
  }
  if (hb==true)//所有线程均已结束,停止等待,
  {
   break;
  }
 }
 FileStream fs;//开始合并
 FileStream fstemp;
 int readfile;
 byte[] bytes=new byte[512];
 fs=new FileStream (textBox3.Text .Trim ().ToString (),System.IO.FileMode.Create);
 for (int k=0;k<thread;k++)
 {
  fstemp=new FileStream (filenamew[k],System.IO.FileMode .Open);
  while (true)
  {
   readfile=fstemp.Read (bytes,0,512);
   if (readfile>0)
   {
    fs.Write (bytes,0,readfile);
   }
   else
   {
    break;
   }
  }
  fstemp.Close ();
 }
 fs.Close ();
 DateTime dt=DateTime.Now;
 textBox1.Text =dt.ToString ();//结束时间
 MessageBox.Show ("接收完毕!!!");
}
 DateTime dt=DateTime.Now;//开始接收时间
 textBox1.Text =dt.ToString ();
 strurl=textBox2.Text .Trim ().ToString ();
 HttpWebRequest request;
 long filesize=0;
 try
 {
  request=(HttpWebRequest)HttpWebRequest.Create (strurl);
  filesize=request.GetResponse ().ContentLength;//取得目标文件的长度
  request.Abort ();
 }
 catch (Exception er)
 {
  MessageBox.Show (er.Message );
 }
 // 接收线程数
 thread=Convert.ToInt32 (textBox4.Text .Trim().ToString (),10);
 //根据线程数初始化数组
 threadw=new bool [thread];
 filenamew=new string [thread];
 filestartw=new int [thread];
 filesizew=new int[thread];

 //计算每个线程应该接收文件的大小
 int filethread=(int)filesize/thread;//平均分配
 int filethreade=filethread+(int)filesize%thread;//剩余部分由最后一个线程完成
 //为数组赋值
 for (int i=0;i<thread;i++)
 {
  threadw[i]=false;//每个线程状态的初始值为假
  filenamew[i]=i.ToString ()+".dat";//每个线程接收文件的临时文件名
  if (i<thread-1)
  {
   filestartw[i]=filethread*i;//每个线程接收文件的起始点
   filesizew[i]=filethread-1;//每个线程接收文件的长度
  }
  else
  {
   filestartw[i]=filethread*i;
   filesizew[i]=filethreade-1;
  }
 }
 //定义线程数组,启动接收线程
 Thread[] threadk=new Thread [thread];
 HttpFile[] httpfile=new HttpFile [thread];
 for (int j=0;j<thread;j++)
 {
  httpfile[j]=new HttpFile(this,j);
  threadk[j]=new Thread(new ThreadStart (httpfile[j].receive ));
  threadk[j].Start ();
 }
 //启动合并各线程接收的文件线程
 Thread hbth=new Thread (new ThreadStart (hbfile));
 hbth.Start ();


34.MP3播放
/*
using System.Runtime.InteropServices;
public static uint SND_ASYNC = 0x0001; // play asynchronously
public static uint SND_FILENAME = 0x00020000; // name is file name
[DllImport("winmm.dll")]
public static extern int mciSendString(string m_strCmd, string m_strReceive, int m_v1, int m_v2);
[DllImport("Kernel32", CharSet = CharSet.Auto)]
static extern Int32 GetShortPathName(String path,StringBuilder shortPath, Int32 shortPathLength);
*/
string name = %%1
StringBuilder shortpath=new StringBuilder(80);
int result=GetShortPathName(name,shortpath,shortpath.Capacity);
name=shortpath.ToString();
mciSendString(@"close all",null,0,0);
mciSendString(@"open "+name+" alias song",null,0,0); //打开
mciSendString("play song",null,0,0); //播放

35.WAV播放
/*
using System.Runtime.InteropServices;
public static uint SND_ASYNC = 0x0001; // play asynchronously
public static uint SND_FILENAME = 0x00020000; // name is file name
[DllImport("winmm.dll")]
public static extern int mciSendString(string m_strCmd, string m_strReceive, int m_v1, int m_v2);
[DllImport("Kernel32", CharSet = CharSet.Auto)]
static extern Int32 GetShortPathName(String path,StringBuilder shortPath, Int32 shortPathLength);
*/
string name = %%1
StringBuilder shortpath=new StringBuilder(80);
int result=GetShortPathName(name,shortpath,shortpath.Capacity);
name=shortpath.ToString();
mciSendString(@"close all",null,0,0);
mciSendString(@"open "+name+" alias song",null,0,0); //打开
mciSendString("play song",null,0,0); //播放

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值