参考这两个C#程序(含注释) 2客户

本文介绍了一个使用C#实现的TCP客户端类,该类提供了连接服务器、读写数据及发送接收消息等功能。通过示例展示了如何使用此类进行基本的网络通信。
/// TCP客户端 [C#源代码来自http://www.showjim.com/]
using System;
using System.Net.Sockets;
using System.IO;
using System.Text;
using sys.dataStructure;

namespace sys.net
{
    /// <summary>
    /// TCP客户端
    /// </summary>
    public class tcpClient
    {
        /// <summary>
        /// TCP客户端连接
        /// </summary>
        private TcpClient client = null;
        /// <summary>
        /// 网络数据流
        /// </summary>
        private NetworkStream stream = null;

        #region 构造客户端TCP连接实例并获取数据流
        /// <summary>
        /// 构造客户端TCP连接实例并获取数据流
        /// </summary>
        /// <param name="serverName">服务器名称</param>
        /// <param name="port">端口</param>
        public tcpClient(string serverName, int port)
        {
            try
            {
                if (port > 0 && port < 65536) stream = (client = new TcpClient(serverName, port)).GetStream();
            }
            catch(Exception error)
            {
                close();
                sys.exception.debug.throwException(System.Reflection.MethodBase.GetCurrentMethod(), "客户端TCP连接失败(" + serverName + ":" + port.ToString() + @")
" + error.ToString());
            }
        }
        #endregion

        #region 关闭客户端TCP连接
        /// <summary>
        /// 关闭客户端TCP连接
        /// </summary>
        ~tcpClient() { close(); }
        /// <summary>
        /// 关闭客户端TCP连接
        /// </summary>
        public void close()
        {
            if (client != null)
            {
                try { client.Close(); client = null; }
                catch { }
            }
            if (stream != null)
            {
                try { stream.Close(); stream = null; }
                catch { }
            }
        }
        #endregion

        #region 流刷新
        /// <summary>
        /// 流刷新
        /// </summary>
        public void flush()
        {
            try { stream.Flush(); }
            catch { close(); }
        }
        #endregion

        #region 从数据流读取数据
        /// <summary>
        /// 从数据流读取一个字节(NetworkStream.ReadByte有Bug并且try不到)
        /// </summary>
        /// <returns>-2表示出错,-1表示结束</returns>
        public int readByte()
        {
            int value = -2;
            byte[] bytes = new byte[1];
            int length = _read(bytes, 0, 1);
            if (length == 1)
            {
                if (bytes == null || bytes.Length == 0) value = -3;
                else value = (int)bytes[0];
            }
            else if (length >= 0) value = -1;
            return value;
        }
        /// <summary>
        /// 从数据流读取一个31位整数
        /// </summary>
        /// <returns>-2表示出错,-1表示结束</returns>
        public int readInt31()
        {
            int value = -2;
            byte[] bytes = new byte[4];
            int length = _read(bytes, 0, 4);
            if (length == 4)
            {
                if ((value = BitConverter.ToInt32(bytes, 0)) < 0) value = 0;
            }
            else if (length >= 0) value = -1;
            return value;
        }
        /// <summary>
        /// 从数据流读取数据到字节数组
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>实际读取长度,失败为-1</returns>
        public int read(byte[] bytes)
        {
            return bytes == null || bytes.Length == 0 ? -1 : _read(bytes, 0, bytes.Length);
        }
        /// <summary>
        /// 从数据流读取数据到字节数组的指定位置
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">开始位置</param>
        /// <returns>实际读取长度,失败为-1</returns>
        public int read(byte[] bytes, int startIndex)
        {
            return bytes == null || startIndex >= bytes.Length ? -1 : _read(bytes, startIndex, bytes.Length - startIndex);
        }
        /// <summary>
        /// 从数据流读取指定长度到字节数组的指定位置
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">开始位置</param>
        /// <param name="length">读取长度</param>
        /// <returns>实际读取长度,失败为-1</returns>
        public int read(byte[] bytes, int startIndex, int length)
        {
            return bytes == null || startIndex < 0 || length <= 0 || startIndex + length > bytes.Length ? -1 : _read(bytes, startIndex, length);
        }
        /// <summary>
        /// 从数据流读取指定长度的字节数组
        /// </summary>
        /// <param name="length">读取长度</param>
        /// <returns>实际读取字节数组</returns>
        public byte[] readBytes(int length)
        {
            byte[] bytes = null;
            if (length > 0)
            {
                int readLength = _read(bytes = new byte[length], 0, length);
                if (readLength != length)
                {
                    if (readLength == -1) bytes = null;
                    else
                    {
                        byte[] newBytes = new byte[readLength];
                        for (int i = 0; i < readLength; i++) newBytes[i] = bytes[i];
                        bytes = newBytes;
                    }
                }
            }
            return bytes;
        }
        /// <summary>
        /// 从数据流读取指定长度到字节数组的指定位置
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">开始位置</param>
        /// <param name="length">读取长度</param>
        /// <returns>实际读取长度,失败为-1</returns>
        private int _read(byte[] bytes, int startIndex, int length)
        {
            int readLength = -1;
            try
            {
                for (int nextLength = length; nextLength != 0; nextLength -= readLength)
                {
                    startIndex += (readLength = stream.Read(bytes, startIndex, nextLength));
                    //System.Threading.Thread.Sleep(10);
                }
                readLength = length;
            }
            catch
            {
                readLength = -1;
                close();
            }
            return readLength;
        }
        /// <summary>
        /// 从数据流读取字节数组直到指定字符结束
        /// </summary>
        /// <param name="endByte">结束字符</param>
        /// <returns>字节数组</returns>
        public byte[] readUntilEnd(byte endByte)
        {
            MemoryStream byteStream = new MemoryStream();
            int read = stream.ReadByte(), end = (int)endByte;
            while (read != -1 && read != end)
            {
                byteStream.WriteByte((byte)read);
                read = stream.ReadByte();
            }
            byte[] bytes = (read == -1 ? null : byteStream.ToArray());
            byteStream.Close();
            return bytes;
        }
        /// <summary>
        /// 从数据流读取字节数组直到指定字符结束
        /// </summary>
        /// <param name="endByte">结束字符</param>
        /// <returns>字节数组</returns>
        public byte[] readUntilEnd(byte[] endByte)
        {
            byte[] bytes = null;
            if (endByte != null && endByte.Length != 0)
            {
                int length = endByte.Length;
                if (length == 1) bytes = readUntilEnd(endByte[0]);
                else
                {
                    int read = stream.ReadByte();
                    if (read != -1)
                    {
                        MemoryStream byteStream = new MemoryStream();
                        int endIndex = 0;
                        int[] end = new int[length];
                        for (int i = 0; i < length; i++) end[i] = (byte)endByte[i];
                        do
                        {
                            if (read != end[endIndex])
                            {
                                if (endIndex != 0)
                                {
                                    byteStream.Write(endByte, 0, endIndex);
                                    endIndex = 0;
                                }
                                byteStream.WriteByte((byte)read);
                                read = stream.ReadByte();
                            }
                            else if ((++endIndex) == length) break;
                        }
                        while (read != -1);
                        bytes = (read == -1 ? null : byteStream.ToArray());
                        byteStream.Close();
                    }
                }
            }
            return bytes;
        }
        #endregion

        #region 发送数据到服务器
        /// <summary>
        /// 发送字节数组到服务器
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>是否成功</returns>
        public bool send(byte[] bytes)
        {
            return bytes != null && bytes.Length > 0 && _send(bytes, 0, bytes.Length);
        }
        /// <summary>
        /// 发送字节数组的指定位置数据到服务器
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">起始位置</param>
        /// <returns>是否成功</returns>
        public bool send(byte[] bytes, int startIndex)
        {
            return bytes != null && startIndex >= 0 && bytes.Length > startIndex && _send(bytes, startIndex, bytes.Length - startIndex);
        }
        /// <summary>
        /// 发送字节数组的指定位置数据到服务器
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="length">发送长度</param>
        /// <returns>是否成功</returns>
        public bool send(byte[] bytes, int startIndex, int length)
        {
            return bytes != null && startIndex >= 0 && length >= 0 && bytes.Length >= startIndex + length && _send(bytes, startIndex, length);
        }
        /// <summary>
        /// 发送字符串到服务器
        /// </summary>
        /// <param name="sendString">字符串</param>
        /// <param name="code">编码方式</param>
        /// <returns>是否成功</returns>
        public bool send(string sendString, Encoding code)
        {
            return sendString != null && sendString.Length != 0 && code != null && _send(code.GetBytes(sendString));
        }
        /// <summary>
        /// 按照默认编码方式发送字符串到服务器
        /// </summary>
        /// <param name="sendString">字符串</param>
        /// <returns>是否成功</returns>
        public bool send(string sendString)
        {
            return sendString != null && sendString.Length != 0 && _send(Encoding.Default.GetBytes(sendString));
        }
        /// <summary>
        /// 发送字节数组到服务器
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>是否成功</returns>
        private bool _send(byte[] bytes)
        {
            bool isSend = true;
            try { stream.Write(bytes, 0, bytes.Length); }
            catch { isSend = false; close(); }
            return isSend;
        }
        /// <summary>
        /// 发送字节数组的指定位置数据到服务器
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="length">发送长度</param>
        /// <returns>是否成功</returns>
        private bool _send(byte[] bytes, int startIndex, int length)
        {
            bool isSend = true;
            try { stream.Write(bytes, startIndex, length); }
            catch { isSend = false; close(); }
            return isSend;
        }
        #endregion

        #region 读取服务器端指定长度数据保存到文件
        /// <summary>
        /// 读取服务器端指定长度数据保存到文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="length">文件字节数</param>
        /// <returns>是否成功</returns>
        public bool saveFile(string fileName, long length)
        {
            bool isSave = false;
            if (fileName != null && fileName.Length != 0 && length > 0)
            {
                FileStream fileStream = null;
                try { fileStream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write, FileShare.None, pub.streamBufferLength); }
                catch { }
                if (fileStream != null)
                {
                    isSave = saveFile(fileStream, 0, length, pub.streamBufferLength);
                    fileStream.Close();
                    if (!isSave) File.Delete(fileName);
                }
            }
            return isSave;
        }
        /// <summary>
        /// 读取服务器端指定长度数据保存到文件流
        /// </summary>
        /// <param name="fileStream">文件流</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="length">字节长度</param>
        /// <returns>是否成功</returns>
        public bool saveFile(FileStream fileStream, long startIndex, long length)
        {
            return saveFile(fileStream, startIndex, length, pub.streamBufferLength);
        }
        /// <summary>
        /// 读取服务器端指定长度数据保存到文件流
        /// </summary>
        /// <param name="fileStream">文件流</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="length">字节长度</param>
        /// <param name="bufferLength">缓存区字节长度</param>
        /// <returns>是否成功</returns>
        public bool saveFile(FileStream fileStream, long startIndex, long length, int bufferLength)
        {
            bool isSave = false;
            if (fileStream != null && startIndex >= 0 && length > 0 && bufferLength > 0)
            {
                long endIndex = startIndex + length;
                if (endIndex > 0)
                {
                    try
                    {
                        fileStream.SetLength(endIndex);
                        fileStream.Seek(startIndex, SeekOrigin.Begin);
                    }
                    catch { }

                    int readLength;
                    byte[] bytes = new byte[bufferLength];
                    isSave = true;
                    try
                    {
                        while (isSave && length >= bufferLength)
                        {
                            if (isSave = ((readLength = read(bytes)) == bufferLength))
                            {
                                fileStream.Write(bytes, 0, readLength);
                                length -= readLength;
                            }
                        }
                        if (isSave && length != 0 && (isSave = (read(bytes, 0, readLength = (int)length) == readLength))) fileStream.Write(bytes, 0, readLength);
                    }
                    catch { isSave = false; }
                }
            }
            return isSave;
        }
        #endregion

        #region 用法示例
        /// <summary>
        /// 服务器端IP
        /// </summary>
        private const string exampleIp = "127.0.0.1";
        /// <summary>
        /// 服务器端监听端口
        /// </summary>
        private const int examplePort = 9999;
        /// <summary>
        /// 用法示例
        /// </summary>
        private static void example()
        {
            sys.net.tcpClient exampleClient = new sys.net.tcpClient(exampleIp, examplePort);

            #region 接收服务器端的数据
            int byteValue = exampleClient.readByte();   //接收一个字节
            int int31Value = exampleClient.readInt31();  //接收一个31位整数
            byte[] bytes = exampleClient.readBytes(int31Value); //接收一个字节数组
            int length = exampleClient.read(bytes, 0, int31Value);    //接收一个字节数组
            #endregion

            #region 发送数据到服务器端
            bool isSend = exampleClient.send(bytes, 0, bytes.Length);  //发送一个字节数组
            #endregion
        }
        #endregion
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值