用C#写的聊天服务端,用到多线程,TCP协议,非点对点。谢谢! 50

服务端主线程监听自己的某个端口,有数据包过来就单开一个线程来处理,数据包里包含的客户端的Email号、内容和接收端的Email号(如果这时候接收端已经连上服务器的话服务器就把数据包处理后转发)。然后这里面用到哈希表,线程间通讯,多线程,互斥等概念吧(我对... 展开
 我来答

答题抽奖

首次认真答题后

即可获得3次抽奖机会,100%中奖。

更多问题
推荐于2016-11-18 13:35:12 最佳答案
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.IO;

class Server
{
    Socket _listenSocket;

    Dictionary<string, ClientProcess> _clients;

    public Server(int port)
    {
        _clients = new Dictionary<string, ClientProcess>();
        _listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint lep = new IPEndPoint(IPAddress.Any, port);
        _listenSocket.Bind(lep);
    }

    public void Start()
    {
        _listenSocket.Listen(5);
        for (; ; )
        {
            Socket client = _listenSocket.Accept();
            ClientProcess cp = new ClientProcess(this, client);
            ThreadStart ts = new ThreadStart(cp.Process);
            Thread t = new Thread(ts);
            t.Start();
        }
    }

    public void AddClient(string email, ClientProcess c)
    {
        lock (_clients)
        {
            if (!_clients.ContainsKey(email))
                _clients.Add(email, c);
        }
    }

    public void RemoveClient(string email)
    {
        lock (_clients)
        {
            if (_clients.ContainsKey(email))
                _clients.Remove(email);
        }
    }

    public void SendTo(string from, string email, string msg)
    {
        ClientProcess cp;
        lock(_clients) {
            _clients.TryGetValue(email, out cp);
        }
        if (cp != null)
        {
            cp.Send(from, msg);
        }
    }
}

class ClientProcess
{
    Server _serv;
    Socket _s;

    TcpClient _tc;
    StreamReader _sr;
    StreamWriter _sw;

    string email;

    public ClientProcess(Server serv, Socket s)
    {
        _serv = serv;
        _s = s;
        _tc = new TcpClient();
        _tc.Client = _s;
        _sr = new StreamReader(_tc.GetStream());
        _sw = new StreamWriter(_tc.GetStream());
    }

    public void Process()
    {
        try
        {
            email = _sr.ReadLine();
            _serv.AddClient(email, this);

            for (; ; )
            {
                string l = _sr.ReadLine();
                int i = l.IndexOf(':');
                if(i == -1)    
                    continue;

                string em = l.Substring(0, i);
                string msg = l.Substring(i + 1);
                _serv.SendTo(email, em, msg);
            }
        }
        catch
        {
            _serv.RemoveClient(email);
        }
    }

    public void Send(string email, string msg)
    {
        _sw.WriteLine("{0}:{1}", email, msg);
        _sw.Flush();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Server s = new Server(12345);
        s.Start();
    }
}

协议是这样的:

1、发送和接收都是以行为单位的

2、客户端连接后发送的第一行数据是自己的邮箱

3、客户端之后发送的格式是:  对方邮箱 冒号 要发送的消息。冒号是英文半角冒号,邮箱和冒号间没有空格

空雪梦见

采纳率:78% 来自团队:快乐之家 擅长: C/C++ C#/.NET VC++

其他回答

用UDP最合适干这事。。在这里,引用你这句 "(如果这时候接收端已经连上服务器的话服务器就把数据包处理后转发)。 " 若是TCP,没连上哪能收到数据?
追问
存入数据库啊,当作离线消息存储
miwen58 | 发布于2013-11-25
评论
留个邮箱 给你发过去一个简单的聊天程序
zhang399401 | 发布于2013-11-25
评论

为您推荐:

×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消