c#基于WinForm的Socket实现简单的聊天室 IM

1:什么是Socket

所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。

从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。

2:客服端和服务端的通信简单流程

3:服务端Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ChartService
{
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using ChatCommoms;
    using ChatModels;

    public partial class ServiceForm : Form
    {
        Socket _socket;
        private static List<ChatUserInfo> userinfo = new List<ChatUserInfo>();
        public ServiceForm()
        {
            InitializeComponent();

        }

        private void btnServicStart_Click(object sender, EventArgs e)
        {
            try
            {
                string ip = textBox_ip.Text.Trim();
                string port = textBox_port.Text.Trim();
                if (string.IsNullOrWhiteSpace(ip) || string.IsNullOrWhiteSpace(port))
                {
                    MessageBox.Show("IP与端口不可以为空!");
                }
                ServiceStartAccept(ip, int.Parse(port));
            }
            catch (Exception)
            {
                MessageBox.Show("连接失败!或者ip,端口参数异常");
            }
        }
        public void ServiceStartAccept(string ip, int port)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint endport = new IPEndPoint(IPAddress.Parse(ip), port);
            socket.Bind(endport);
            socket.Listen(10);
            Thread thread = new Thread(Recevice);
            thread.IsBackground = true;
            thread.Start(socket);
            textboMsg.AppendText("服务开启ok...");
        }

        /// <summary>
        /// 开启接听服务
        /// </summary>
        /// <param name="obj"></param>
        private void Recevice(object obj)
        {
            var socket = obj as Socket;
            while (true)
            {
                string remoteEpInfo = string.Empty;
                try
                {
                    Socket txSocket = socket.Accept();
                    _socket = txSocket;
                    if (txSocket.Connected)
                    {
                        remoteEpInfo = txSocket.RemoteEndPoint.ToString();
                        textboMsg.AppendText($"\r\n{remoteEpInfo}:连接上线了...");
                        var clientUser = new ChatUserInfo
                        {
                            UserID = Guid.NewGuid().ToString(),
                            ChatUid = remoteEpInfo,
                            ChatSocket = txSocket
                        };
                        userinfo.Add(clientUser);

                        listBoxCoustomerList.Items.Add(new ChatUserInfoBase { UserID = clientUser.UserID, ChatUid = clientUser.ChatUid });
                        listBoxCoustomerList.DisplayMember = "ChatUid";
                        listBoxCoustomerList.ValueMember = "UserID";

                        ReceseMsgGoing(txSocket, remoteEpInfo);
                    }
                    else
                    {
                        if (userinfo.Count > 0)
                        {
                            userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault());
                            //移除下拉框对于的socket或者叫用户
                        }
                        break;
                    }
                }
                catch (Exception)
                {
                    if (userinfo.Count > 0)
                    {
                        userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault());
                        //移除下拉框对于的socket或者叫用户
                    }
                }
            }

        }

        /// <summary>
        /// 接受来自客服端发来的消息
        /// </summary>
        /// <param name="txSocket"></param>
        /// <param name="remoteEpInfo"></param>
        private void ReceseMsgGoing(Socket txSocket, string remoteEpInfo)
        {

            //退到一个客服端的时候 int getlength = txSocket.Receive(recesiveByte); 有抛异常
            Thread thread = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        byte[] recesiveByte = new byte[1024 * 1024 * 4];
                        int getlength = txSocket.Receive(recesiveByte);
                        if (getlength <= 0) { break; }

                        var getType = recesiveByte[0].ToString();
                        string getmsg = Encoding.UTF8.GetString(recesiveByte, 1, getlength - 1);
                        ShowMsg(remoteEpInfo, getType, getmsg);
                    }
                    catch (Exception)
                    {
                        //string userid = userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo)?.ChatUid;
                        listBoxCoustomerList.Items.Remove(remoteEpInfo);
                        userinfo.Remove(userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo));//从集合中移除断开的socket

                        listBoxCoustomerList.DataSource = userinfo;//重新绑定下来的信息
                        listBoxCoustomerList.DisplayMember = "ChatUid";
                        listBoxCoustomerList.ValueMember = "UserID";
                        txSocket.Dispose();
                        txSocket.Close();
                    }
                }
            });
            thread.IsBackground = true;
            thread.Start();

        }

        private void ShowMsg(string remoteEpInfo, string getType, string getmsg)
        {
            textboMsg.AppendText($"\r\n{remoteEpInfo}:消息类型:{getType}:{getmsg}");
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            this.textBox_ip.Text = "192.168.1.101";//初始值
            this.textBox_port.Text = "50000";
        }

        /// <summary>
        /// 服务器发送消息,可以先选择要发送的一个用户
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            var getmSg = textBoxSendMsg.Text.Trim();
            if (string.IsNullOrWhiteSpace(getmSg))
            {
                MessageBox.Show("要发送的消息不可以为空", "注意"); return;
            }
            var obj = listBoxCoustomerList.SelectedItem;
            int getindex = listBoxCoustomerList.SelectedIndex;
            if (obj == null || getindex == -1)
            {
                MessageBox.Show("请先选择左侧用户的用户"); return;
            }
            var getChoseUser = obj as ChatUserInfoBase;
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum);
            userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket?.Send(sendMsg);
        }

        /// <summary>
        /// 给所有登录的用户发送消息,群发了
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            var getmSg = textBoxSendMsg.Text.Trim();
            if (string.IsNullOrWhiteSpace(getmSg))
            {
                MessageBox.Show("要发送的消息不可以为空", "注意"); return;
            }
            if (userinfo.Count <= 0)
            {
                MessageBox.Show("暂时没有客服端登录!"); return;
            }
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum);
            foreach (var usersocket in userinfo)
            {
                usersocket.ChatSocket?.Send(sendMsg);
            }
        }

        /// <summary>
        /// 服务器给发送震动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendSnak_Click(object sender, EventArgs e)
        {
            var obj = listBoxCoustomerList.SelectedItem;
            int getindex = listBoxCoustomerList.SelectedIndex;
            if (obj == null || getindex == -1)
            {
                MessageBox.Show("请先选择左侧用户的用户"); return;
            }
            var getChoseUser = obj as ChatUserInfoBase;

            byte[] sendMsgByte = ServiceSockertHelper.GetSendMsgByte("", ChatTypeInfoEnum.Snake);
            userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket.Send(sendMsgByte);
        }

    }
}

4:客服端Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ChatClient
{
    using ChatCommoms;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            this.textBoxIp.Text = "192.168.1.101";//先初始化一个默认的ip等
            this.textBoxPort.Text = "50000";
        }

        Socket clientSocket;
        /// <summary>
        /// 客服端连接到服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnServicStart_Click(object sender, EventArgs e)
        {
            try
            {
                var ipstr = textBoxIp.Text.Trim();
                var portstr = textBoxPort.Text.Trim();
                if (string.IsNullOrWhiteSpace(ipstr) || string.IsNullOrWhiteSpace(portstr))
                {
                    MessageBox.Show("要连接的服务器ip和端口都不可以为空!");
                    return;
                }
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(IPAddress.Parse(ipstr), int.Parse(portstr));
                labelStatus.Text = "连接到服务器成功...!";
                ReseviceMsg(clientSocket);

            }
            catch (Exception)
            {
                MessageBox.Show("请检查要连接的服务器的参数");
            }
        }
        private void ReseviceMsg(Socket clientSocket)
        {

            Thread thread = new Thread(() =>
             {
                 while (true)
                 {
                     try
                     {
                         Byte[] byteContainer = new Byte[1024 * 1024 * 4];
                         int getlength = clientSocket.Receive(byteContainer);
                         if (getlength <= 0)
                         {
                             break;
                         }
                         var getType = byteContainer[0].ToString();
                         string getmsg = Encoding.UTF8.GetString(byteContainer, 1, getlength - 1);

                         GetMsgFomServer(getType, getmsg);
                     }
                     catch (Exception ex)
                     {
                     }
                 }
             });
            thread.IsBackground = true;
            thread.Start();

        }

        private void GetMsgFomServer(string strType, string msg)
        {
            this.textboMsg.AppendText($"\r\n类型:{strType};{msg}");
        }

        /// <summary>
        /// 文字消息的发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            var msg = textBoxSendMsg.Text.Trim();
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(msg, ChatModels.ChatTypeInfoEnum.StringEnum);
            int sendMsgLength = clientSocket.Send(sendMsg);
        }
    }
}

5:测试效果:

6:完整Code GitHUb下载路径

https://github.com/zrf518/WinformSocketChat.git

7:这个只是一个简单的聊天练习Demo,待进一步完善(实现部分功能,传递的消息byte[0]为消息的类型,用来判断是文字,还是图片等等),欢迎大家指教

以上就是c#基于WinForm的Socket实现简单的聊天室 IM的详细内容,更多关于c# WinForm实现聊天室 IM的资料请关注我们其它相关文章!

(0)

相关推荐

  • C# Socket编程实现简单的局域网聊天器的示例代码

    前言 最近在学习C# Socket相关的知识,学习之余,动手做了一个简单的局域网聊天器.有萌生做这个的想法,主要是由于之前家里两台电脑之间想要传输文件十分麻烦,需要借助QQ,微信或者其他第三方应用,基本都要登录,而且可能传输的文件还有大小限制,压缩问题.所以本聊天器的首要目标就是解决这两个问题,做到使用方便(双击启动即用),传文件无限制. 废话不多说,先上图.S-Chat是服务端,C-Chat是客户端,两者除了客户端首次启动后需要设置一下连接的IP地址外,无其他区别.操作与界面都完全相同,对于用

  • C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)

    扩展: 由于server端是存储了所有server与client的连接对象,因此我们是可以基于此demo的基础上实现聊天系统: * 每当一个与用户发言时,是由server接收到的某个用户的发言信息的,此时服务器端可以通过循环发送该用户发送的信息给每个已经连接连接的用户(排除发送者). Server端代码: class Program { //创建一个和客户端通信的套接字 static Socket SocketWatch = null; //定义一个集合,存储客户端信息 static Dicti

  • C#聊天程序服务端与客户端完整实例代码

    本文所述为基于C#实现的多人聊天程序服务端与客户端完整代码.本实例省略了结构定义部分,服务端主要是逻辑处理部分代码,因此使用时需要完善一些窗体按钮之类的. 先看服务端代码如下: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Net; using

  • c#多线程网络聊天程序代码分享(服务器端和客户端)

    XuLIeHua类库 复制代码 代码如下: using System;using System.Collections;  using System.Collections.Generic;using System.Threading;  using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using System.Text;using System.IO;using Sy

  • 基于c#用Socket做一个局域网聊天工具

    程序设计成为简单的服务端和客户端之间的通信, 但通过一些方法可以将这两者进行统一起来, 让服务端也成为客户端, 让客户端也成为服务端, 使它们之间可以互相随时不间断的通信. 考虑到实现最原始的服务端和客户端之间的通信所需要的步骤对于写这样的程序是很有帮助的. 作为服务端, 要声明一个Socket A并绑定(Bind)某一个IP+这个IP指定的通信端口, 比如这个是127.0.0.1:9050, 然后开始监听(Listen), Listen可以监听来自多个IP传过来的连接请求, 具体可以同时连接几

  • C#基于UDP实现的P2P语音聊天工具

    语音获取 要想发送语音信息,首先得获取语音,这里有几种方法,一种是使用DirectX的DirectXsound来录音,我为了简便使用一个开源的插件NAudio来实现语音录取. 在项目中引用NAudio.dll //------------------录音相关----------------------------- private IWaveIn waveIn; private WaveFileWriter writer; private void LoadWasapiDevicesCombo(

  • C#实现简单聊天程序的方法

    本文实例讲述了C#简单聊天程序实现方法.分享给大家供大家参考.具体如下: 假如有服务器端程序,ChatServer和客户端程序ChatClient.实现客户端向服务器端发送信息的简单功能. 运行步骤, 1.先是服务器端start listen, 2.然后客户端connect. 3.客户端发送消息   只要服务器端start listen了,然后客户端也connect了.这样建立起连接后.接受发送信息就方便了,只要用writer,reader去操作NetworkStream   服务器ChatSe

  • c# 实现语音聊天的实战示例

    一.语音聊天说专业点就是即时语音,是一种基于网络的快速传递语音信息的技术,普遍应用于各类社交软件中,优势主要有以下几点: (1)时效性:视频直播会因为带宽问题有时出现延迟高的问题,而语音直播相对来说会好很多,延迟低,并且能够第·一时间与听众互动,时效性强. (2)隐私性:这一点体现在何处,如主播不想暴露自己的长相,或者进行问题回答是,没有视频的话会让主播感到更安心,所以语音直播隐私性更强. (3)内容质量高:因为语音直播不靠"颜值"只有好的内容才能够吸引用户,所以语音直播相对来说内容质

  • c#实现多线程局域网聊天系统

    觉得好有点帮助就顶一下啦. socke编程,支持多客户端,多线程操作避免界面卡死. 开启socket private void button1_Click(object sender, EventArgs e) { try { int port = int.Parse(txt_port.Text); string host = txt_ip.Text; //创建终结点 IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEnd

  • C#基于Windows服务的聊天程序(1)

    本文将演示怎么通过C#开发部署一个Windows服务,该服务提供各客户端的信息通讯,适用于局域网.采用TCP协议,单一服务器连接模式为一对多:多台服务器的情况下,当客户端连接数超过预设值时可自动进行负载转移,当然也可手动切换服务器,这种场景在实际项目中应用广泛. 简单的消息则通过服务器转发,文件类的消息则让客户端自己建立连接进行传输.后续功能将慢慢完善. 自定义协议: 1.新建Windows服务项目 2.修改配置文件添加 <appSettings> <add key="maxQ

  • C#使用Socket实现局域网聊天

    本文实例为大家分享了C#使用Socket实现局域网聊天的具体代码,供大家参考,具体内容如下 先运行一个java写的局域网聊天,效果图如下 后使用c#图形修改如下: C#代码: servlet服务端 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using Sys

  • C#制作简单的多人在线即时交流聊天室

    实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSocket,当然HTML5目前在PC端并没有被所有浏览器支持,所以我的这个聊天室仍是基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室,这个聊天室其实是我上周周末完成的,功能简单,可能有些不足,但可以满足在线即时聊天需求,分享也是给大家提供一个思路,大家可以基于此来实现更好的在线即时聊

  • 分享一个C#编写简单的聊天程序(详细介绍)

    引言 这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编程基础(篇外篇).聊天程序的实现模式.程序实现. 程序的分析与设计 1.明确程序功能 如果大家现在已经参加了工作,你的经理或者老板告诉你,"小王,我需要你开发一个聊天程序".那么接下来该怎么做呢?你是不是在脑子里有个雏形,然后就直接打开VS2005开始设计窗体,编写代码了呢?在开始之

随机推荐