你也可以写个聊天程序 - C# Socket学习1

阅读目录

简述

我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解。我今天就来和大家一起学习下Socket,并写一个简单的聊天程序。

一些基础类

首先我们每天打开浏览器访问网页信息都是使用的HTTP/HTTPS协议,而HTTP是通过的TCP建立的连接。TCP底层又是通过的Socket套接字进行的通信。所以他们之间的抽象关系是:

我们在学习Socket编程的时候可能会需要用到IPEndPoint、Dns、IPAddress等类,再往上TCP相关有TcpListener、TcpClient、NetworkStream,再往上就是大家熟悉的HttpClient等。
IPEndPoint、Dns、IPAddress基础作用如下:

//根据DNS获取域名绑定的IP
foreach (var address in Dns.GetHostEntry("www.baidu.com").AddressList)
{
    Console.WriteLine($"百度IP:{address}");
}

//字符串转IP地址
IPAddress ipAddress = IPAddress.Parse("192.168.1.101");

//通过IP和端口构造IPEndPoint对象,用于远程连接
//通过IP可以确定一台电脑,通过端口可以确定电脑上的一个程序
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 80);

利用Socket编写聊天程序

我们首先从Socket开始讲起。
要实现Socket通信,先得有个服务端的监听,再有个客户端的连接,然后客户端和服务端就可以通信了。如下:

服务端代码如下:

//1 创建Socket对象
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//2 绑定ip和端口
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001);
socketServer.Bind(ipEndPoint);

//3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
socketServer.Listen(10);

//4、【阻塞】,等待客户端连接
Socket newSocket = socketServer.Accept();

//5、【阻塞】,等待读取客户端发送过来的数据
byte[] data = new byte[1024 * 1024];
int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None);

//6、读取数据
var msg = Encoding.UTF8.GetString(data, 0, readLeng);

客户端代码如下:

//1 创建Socket对象
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//2 连接到服务端
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001);
socketClient.Connect(ipEndPoint);

//3 发送消息到服务端
socketClient.Send(Encoding.UTF8.GetBytes("你好,农码一生"));

到此,我们就可以开启服务端的服务,并接受客户端的发来的消息了。
不过,这里有个很大的问题,服务端只能建立一个客户端连接和接受一次客户端发来的消息。如果想要连接更多的客户端和接受无数次的消息,服务端代码两处阻塞的地方需要另外开一个线程然后包到循环里面去。
修改后的服务端代码如下:

void .... ()
{
    //1 创建Socket对象
    socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //2 绑定ip和端口
    IPAddress ip = IPAddress.Parse("127.0.0.1");
    IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001);
    socketServer.Bind(ipEndPoint);

    //3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
    socketServer.Listen(10);

    //开启新的线程,循环等待新的客户端连接
    Task.Run(() => { Accept(socketServer); });
}

void Accept(Socket socket)
{
    while (true)
    {
        //4、【阻塞】,等待客户端连接
        Socket newSocket = socket.Accept();

        //开启新的线程,循环等待接收新的数据
        Task.Run(() => { Receive(newSocket); });
    }
}

void Receive(Socket newSocket)
{
    while (true)
    {
        //5、【阻塞】,等待读取客户端发送过来的数据
        byte[] data = new byte[1024 * 1024];
        int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None);

        //6、读取数据
        var msg = Encoding.UTF8.GetString(data, 0, readLeng);
    }
} 

到此,服务端就可以接受多个客户端的连接和接收多次客户端发来的消息了。不过我们可能还需客服端能接收服务端发来的消息,这个你可以自己尝试下。文末会提供完整的代码参考。

注意:
用Socket来编写聊天软件是长连接,有状态的。不确定服务端什么时候会发送消息过来,我们也可以连续发送消息而不响应。所以,对于消息的接收就需要开一个新的线程循环接收。
而对于HTTP来说,虽然它是也是通过TCP建立的通信,但在数据请求完毕后会马上关闭连接,这个过程很短。每次访问都会建立一个新的连接,是无状态的。
对于浏览器来说是一问一答的形式,先发送请求(Send),然后接收响应(Receive)所以就可以做到不开启新的线程,直接有序的同步的完成。这个在下一篇《模拟浏览器的请求和服务端的响应》会具体分析。

利用TCP编写聊天程序

虽然上面我们利用Socket类实现了一个简单的聊天程序,但是微软觉得Socket太复杂。为了让你们早点干完活,早点下班,于是又在Socket的基础上有封装了两个相关的类TcpListener、TcpClient。
利用TcpListener、TcpClient来实现同上面相同的功能。
服务端代码:

void ...()
{
    //1 开启监听
    TcpListener tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9999);
    tcpListener.Start(10); //最多同时接收10个用户连接

    //开启一个线程,循环等待客户端的连接
    Task.Run(() => { Accept(); });
}

//等待客户端的连接
void Accept()
{
    while (true)
    {
        //2 【阻塞】等待客户端的连接
        TcpClient tcpClient = tcpListener.AcceptTcpClient();
        NetworkStream networkStream = tcpClient.GetStream();

        //开启一个新的线程 等待新的消息
        Task.Run(() => { Read(networkStream, tcpClient); });
    }
}

//接收消息
void Read(NetworkStream networkStream)
{
    while (true)
    {
        byte[] buffer = new byte[1024 * 1024];
        //3 【阻塞】等待接收新的消息
        var readLen = networkStream.Read(buffer, 0, buffer.Length);
        var msg  = Encoding.UTF8.GetString(buffer, 0, readLen);
    }
}

客户端代码:

//1 连接服务端
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));

//2 发送消息到服务端
byte[] buffer = Encoding.UTF8.GetBytes("你好,农码一生");
networkStream.Write(buffer, 0, buffer.Length);

用TcpListener、TcpClient的实现也算ok了,TcpListener代码写的服务端和Socket通信也是完成没问题的,因为他们最后都是Socket。
对此你有觉得比Socket简单和容易理解?其实我更习惯Socket。

注意:

// 1、断开连接使用
socketClient?.Shutdown(SocketShutdown.Both);
socketClient?.Close();

// 2、服务端需要判断
int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None);
if (readLeng == 0)//客户端断开连接
{
    //停止会话(禁用Socket上的发送和接收,该方法允许Socket对象一直等待,直到将内部缓冲区的数据发送完为止)
    newSocket.Shutdown(SocketShutdown.Both);
    //关闭连接
    newSocket.Close();
    //跳出循环
    return;
}

3、具体请参考文末提供的完整demo

效果图

转载:https://www.cnblogs.com/zhaopei/p/Socket1.html

原文地址:https://www.cnblogs.com/BluceLee/p/11671080.html

时间: 2024-11-02 12:15:33

你也可以写个聊天程序 - C# Socket学习1的相关文章

一个简易的聊天程序(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.Th

你也可以写个服务器 - C# Socket学习2

续上篇<你也可以写个聊天程序 - C# Socket学习1> 前言 这里说的服务器是Web服务器,是类似IIS.Tomcat之类的,用来响应浏览器请求的服务. Socket模拟浏览器的Url Get请求 首先浏览器的请求是HTTP协议.我们上一篇说过,HTTP是短连接,用完就断开,是无状态的.所以我们在等待响应的时候不需要另外开个线程循环等待. 也就是我们只需要通过Socket和服务器建立连接,然后发送请求,然后接收服务器的响应,这样就完成了一次请求. 可是,我们一般访问网页的时候都是通过域名

java Socket多线程聊天程序(适合初学者)

一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者 下面是服务器端代码 package tk.socket; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.Act

Node.js + Web Socket 打造即时聊天程序嗨聊

前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术.像node.js这样的后端开拓者直接将前端人员的能力扩大到了后端.瞬间就有了一统天下的感觉,来往穿梭于前后端之间代码敲得飞起,从此由前端晋升为'前后端'. 图片来自G+ 本文将使用Node.js加web socket协议打造一个网页即时聊天程序,取名为HiChat,中文翻过来就是'嗨聊',听中文名有点像是专为寂寞单身男女打造的~ 其中将会使用到express和socket.io两个包模块,下面会有介绍

在windows环境下用C++完成一个hello/hi网络聊天程序

经过网络程序设计课程的学习,我们了解了socket网络程序编程,接下来,就要学以致用,完成一个hello/hi的网络聊天程序. Socket介绍  Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部. Socket起源于Unix,而Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/re

聊天程序(基于Socket、Thread)

聊天程序简述 1.目的:主要是为了阐述Socket,以及应用多线程,本文侧重Socket相关网路编程的阐述.如果您对多线程不了解,大家可以看下我的上一篇博文浅解多线程 . 2.功能:此聊天程序功能实现了服务端跟多个客户端之间的聊天,可以群发消息,选择ip发消息,客户端向服务端发送文件. (例子为WinForm应用程序) Socket,端口,Tcp,UDP. 概念 1.Socket还被称作"套接字",应用程序通常通过套接字向网络发送请求或者应答网络请求.根据连接启动的方式以及本地套接字要

Socket聊天程序——初始设计

写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答(问题A,问题B),那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了几个晚上的空闲时间敲了一个,目前仅支持单聊,群聊,文件传送这些功能.首先,贴出一个丑丑的程序图(UI是用java swing写的,这个早就忘光了,无奈看着JDK的API写了一个),如下图: 服务端设计: 服务端主要有两个操作,一是阻塞接收客户端的socket并做响应处理,二是检测客户端的心跳,如果客

Socket聊天程序——客户端

写在前面: 上周末抽点时间把自己写的一个简单Socket聊天程序的初始设计和服务端细化设计记录了一下,周二终于等来毕业前考的软考证书,然后接下来就是在加班的日子度过了,今天正好周五,打算把客户端的详细设计和Common模块记录一下,因为这个周末开始就要去忙其他东西了. 设计: 客户端设计主要分成两个部分,分别是socket通讯模块设计和UI相关设计. 客户端socket通讯设计: 这里的设计其实跟服务端的设计差不多,不同的是服务端是接收心跳包,而客户端是发送心跳包,由于客户端只与一个服务端进行通

Socket网络编程--聊天程序(3)

上一小节,已经讲到可以每个人多说话,而且还没有限制,简单的来说,我们已经完成了聊天的功能了,那么接下来我们要实现什么功能呢?一个聊天程序至少应该支持一对多的通讯吧,接下来就实现多个客户端往服务器发送数据,和服务器向多个客户端发送数据. 多对一,单向,各个客户端都可以向服务器发送数据 close函数 #include <unistd.h> int close(int sockfd); //用于关闭所打开的Socket套接字 返回值:如果为0表示成功,-1表示失败 处理的办法是每一个客户端连接到服