一个简易的聊天程序(Socket)

效果图:

服务端Server代码:

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

namespace Socket网络编程_Server
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                //当点击开始监听的时候 在服务器端创建一个负责监IP地址跟端口号的Socket
                Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Any;
                //创建端口号对象
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
                //监听
                socketWatch.Bind(point);
                ShowMsg("监听成功");
                socketWatch.Listen(10);

                Thread th = new Thread(Listen);
                th.IsBackground = true;
                th.Start(socketWatch);
            }
            catch
            { }

        }

        /// <summary>
        /// 等待客户端的连接 并且创建与之通信用的Socket
        /// </summary>
        Socket socketSend;
        void Listen(Object o)//线程所执行的函数,如果有参数,必须是Object类型
        {
            Socket socketWatch = o as Socket;
            //等待客户端的连接 并且创建一个负责通信的Socket
            while (true)
            {
                try
                {
                    //负责跟客户端通信的Socket
                    socketSend = socketWatch.Accept();
                    //将远程连接的客户端的IP地址和Socket存入集合中
                    dicSocket.Add(socketSend.RemoteEndPoint.ToString(),socketSend);
                    //将远程连接的客户端的IP地址和Socket存入到下拉框中
                    cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
                    //192.168.11.87:连接成功
                    ShowMsg(socketSend.RemoteEndPoint.ToString() + ":连接成功");
                    //开启一个新线程,不停的接收客户端发来的消息
                    Thread th = new Thread(Recive);
                    th.IsBackground = true;
                    th.Start(socketSend);
                }
                catch
                { }

            }
        }

        //将远程连接的客户端的IP地址和Socket存入集合中
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

        /// <summary>
        /// 服务器端不停的接收客户端发来的消息
        /// </summary>
        /// <param name="o"></param>
        void Recive(Object o)
        {
            Socket socketSend = o as Socket;
            while (true)
            {
                try
                {
                    //客户端连接成功后,服务器应该接受客户端发来的信息
                    byte[] buffer = new byte[1024 * 1024 * 2];
                    //实际接收到的有效字节数
                    int r = socketSend.Receive(buffer);
                    if (r == 0)
                    {
                        break;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, r);
                    ShowMsg(socketSend.RemoteEndPoint + ":" + str);
                }
                catch
                { }
            }
        }

        void ShowMsg(string str)
        {
            txtLog.AppendText(str + "\r\n");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 服务器给客户端发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                string str = txtMsg.Text;
                byte[] buffer = Encoding.UTF8.GetBytes(str);

                List<byte> list = new List<byte>();
                list.Add(0);
                list.AddRange(buffer);
                //将泛型集合转换为集合
                byte[] newBuffer = list.ToArray();

                //获得用户在下拉框总选中的IP地址
                string ip = cboUsers.SelectedItem.ToString();
                dicSocket[ip].Send(newBuffer);
                //socketSend.Send(buffer);
            }
            catch
            {}

        }

        /// <summary>
        /// 选择要发送的文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelect_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "请选择";
            ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
            ofd.Filter = "所有文件|*.*";
            ofd.ShowDialog();

            txtPath.Text = ofd.FileName;
        }

        private void btnSendFile_Click(object sender, EventArgs e)
        {
            //获得要发送文件的路径
            string path = txtPath.Text;
            using (FileStream fsRead=new FileStream(path,FileMode.Open,FileAccess.Read))
            {
                byte[] buffer = new byte[1024 * 1024 * 5];

                int r = fsRead.Read(buffer, 0, buffer.Length);

                List<byte> list = new List<byte>();
                list.Add(1);
                list.AddRange(buffer);
                byte[] newBuffer = list.ToArray();
                dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r+1, SocketFlags.None);
            }
        }

        /// <summary>
        /// 发送震动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnZD_Click(object sender, EventArgs e)
        {
            byte[] buffer = new byte[1];
            buffer[0] = 2;
            dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
        }
    }
}

客户端Client代码:

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

namespace Socket网络编程_Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Socket socketSend;
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                //创建负责通信的Socket    1:表示IP v4     2:什么类型的流,流氏的   3:对应的服务
                socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //需要将文本框的IP地址转换成IPAddress类型
                IPAddress ip = IPAddress.Parse(txtServer.Text);
                //需要将端口号转换成IPEndPoint类型
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
                //获得要连接的远程服务器应用程序的IP地址和端口号
                socketSend.Connect(point);

                ShowMsg("连接成功");

                //开启一个新的线程不停的接收服务器端发来的消息
                Thread th = new Thread(Recive);
                th.IsBackground = true;
                th.Start();
            }
            catch { }
        }

        /// <summary>
        /// 不停的接收服务器发来的消息
        /// </summary>
        void Recive()
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    //实际接收到的有效字节数
                    int r = socketSend.Receive(buffer);
                    if (r == 0)
                    {
                        break;
                    }

                    //先拿到第一位,判断发送的是否文字消息
                    if (buffer[0] == 0)
                    {
                        //注意解码的时候要从第一个开始到长度-1个字节
                        string s = Encoding.UTF8.GetString(buffer, 1, r-1);
                        ShowMsg(socketSend.RemoteEndPoint + ":" + s);
                    }
                    if (buffer[0] == 1)
                    {
                        SaveFileDialog sfd = new SaveFileDialog();
                        sfd.InitialDirectory = @"C:\Users\Administrator\Desktop";
                        sfd.Title = "请选择要保存的文件";
                        sfd.Filter = "所有文件|*.*";
                        sfd.ShowDialog(this);//不加this弹不出?
                        string path = sfd.FileName;
                        using (FileStream fsWrite=new FileStream(path,FileMode.OpenOrCreate,FileAccess.Write))
                        {
                            fsWrite.Write(buffer,1,r-1);
                        }
                        MessageBox.Show("保存成功 ");
                    }
                    if (buffer[0] == 2)
                    {
                        ZD();
                    }
                }
                catch { }
            }
        }

        /// <summary>
        /// 震动
        /// </summary>
        void ZD()
        {
            for (int i = 0; i < 500; i++)
            {
                this.Location = new Point(200, 200);
                this.Location = new Point(280,280);
            }
        }

        void ShowMsg(string str)
        {
            txtLog.AppendText(str + "\r\n");
        }

        /// <summary>
        /// 客户端给服务器发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            string str = txtMsg.Text.Trim();
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            socketSend.Send(buffer);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

    }
}
时间: 2024-10-10 08:16:40

一个简易的聊天程序(Socket)的相关文章

socket实现的一个基本点对点聊天程序

多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口. 服务器监听是指服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态. 客户端请求是由客户端的套接字提出连接请求,要连接的目标是服务器端套接字.为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后再向服务器端套接字提出连接请求.

利用map的特性做一个简易的投票程序

pair 1. 概念:pair是 一种模版类型,每个pair 可以存储两个值,这两种值的类型无限制.也可以将自己写的struct类型的的对象放进去. 2. 用法: pair<int ,int >p (1,2); pair<int ,int > p1= make_pair(1,2); 3. 编写程序读入一系列string和int型数据,将每一组存储在一个pair对象中,然后将这些pair对象存储在vector容器并显示 #include<iostream> #includ

如何用 Python 写一个简易的抽奖程序

不知道有多少人是被这个头图骗进来的:) 事情的起因是这样的,上周有同学问小编,看着小编的示例代码敲代码,感觉自己也会写了,如果不看的话,七七八八可能也写的出来,但是一旦自己独立写一段程序,感觉到无从下手. 其实这个很正常,刚开始学习写代码,都是跟着别人的套路往下写,看的套路少,很难形成自己的套路,这就和做数学题是一样的,做一道题就想会所有的题目,这个可能性微乎其微,都是通过大量的练习来摸索到自己的套路. 正好快过年了,各个公司都会搞一些抽奖活动,小编今天就来聊一下,如果要写一个简单的抽奖程序,小

C 基于UDP实现一个简易的聊天室

引言 本文是围绕Linux udp api 构建一个简易的多人聊天室.重点看思路,帮助我们加深 对udp开发中一些api了解.相对而言udp socket开发相比tcp socket开发注意的细节要少很多. 但是水也很深. 本文就当是一个demo整合帮助开发者回顾和继续了解 linux udp开发的基本流程. 首先我们来看看 linux udp 和 tcp的异同. /* 这里简单比较一下TCP和UDP在编程实现上的一些区别: TCP流程 建立一个TCP连接需要三次握手,而断开一个TCP则需要四个

从一个简单的聊天程序SimpleChat看VPN技术

SimpleVPN写好了以后,感觉比较简单,我觉得只有简单的东西才经得起折腾,才能全民折腾,所以说SimpleVPN还不够简单,本文来一个更加简单的,展示一个超级简单的点对点聊天程序,而且还带简单加密哦.顺便,我们再来看下,到底什么是VPN以及怎样实现它.       QQ如今才刚刚行过成年之礼,典型的90后00前,却早已到了后浪把前浪拍到岸边的砍儿,果不其然,被10后的微信给逆袭了...好在都是腾讯的,这就把竞争收敛到了公司内部,不然这将意味着一个巨人的倒下,太可怕了.多年前,很多人逆向过QQ

一个简易的日志程序

在程序开发过程中,我们经常要记录各种操作信息以及系统信息到日志中,以便于以后查找相关记录或者在遇到程序出现错误时查找错误的原因.一般日志存储于两种介质中:一.存储入数据库,另一种存储于文本文档中.我们最常用的插件有log4.net等.但是对我们日常的小程序来说,它可能过重,所以我自己在自己的开发中写了一个简单的小程序以适应小程序的需要. 为方便自己以后查找,记录代码如下: 1 using System; 2 using System.Collections.Generic; 3 using Sy

任务02——安装 Intellj IDEA,编写一个简易四则运算小程序,并将代码提交到 GitHub

GITHUB:  https://github.com/lalacllla 代码(不完善): https://github.com/lalacllla/CALTMP/blob/master/src/caltmp.java 1.Intellj IDEA的安装和项目的新建并没有什么困难,个人认为Intellj IDEA相对于ECLIPSE更容易上手,界面更加简洁. 2.初步了解Git以及Github的使用,如何简单的创建一个repository,如何上传自己的代码. 3.代码部分还是有比较多的问题需

任务2--安装Intellj IDEA,编写一个简易四则运算小程序,并将代码提交到GitHub

我的GitHub地址为:https://github.com/Orangeyc123 首先呢,我并没有完整的完成任务,我觉得主要问题有以下几个 1.由于之前都没有听说过intellj IDEA这个软件,安装的时候就碰到了好多问题.对于我这个人来说呢,有一点很大的毛病就是对于从来没见过不知道的东西有一种畏惧心理.怕自己装的不对,怕自己有哪一个步骤和别人不一样而产生不同的结果. 比如 之前一直没有遇到过这种情况,显然有些不知所措,不过还好,问了学长以后我想以后出现这种问题应该so easy. 下载并

UDP实现一个简易的聊天室 (Unity&amp;&amp;C#完成)

效果展示(尚未完善) ChatUDPClientTest using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Threading; using System.Net; using System.Net.Sockets; using System.Text; using Common; using UIWidgetsSamples; using System; ///