Socket编程 (连接,发送消息) (Tcp、Udp) - Part1

news/2024/9/17 9:16:50/ 标签: tcp/ip, udp, 网络协议

Socket编程 (连接,发送消息) (Tcp、Udp)


本篇文章主要实现Socket在Tcp\Udp协议下相互通讯的方式。(服务器端与客户端的通讯)

1.基于Tcp协议的Socket通讯类似于B/S架构,面向连接,但不同的是服务器端可以向客户端主动推送消息。

使用Tcp协议通讯需要具备以下几个条件:

(1).建立一个套接字(Socket)

(2).绑定服务器端IP地址及端口号–服务器端

(3).利用Listen()方法开启监听–服务器端

(4).利用Accept()方法尝试与客户端建立一个连接–服务器端

(5).利用Connect()方法与服务器建立连接–客户端

(5).利用Send()方法向建立连接的主机发送消息

(6).利用Recive()方法接受来自建立连接的主机的消息(可靠连接)
在这里插入图片描述
 2.基于Udp协议是无连接模式通讯,占用资源少,响应速度快,延时低。至于可靠性,可通过应用层的控制来满足。(不可靠连接)

(1).建立一个套接字(Socket)

(2).绑定服务器端IP地址及端口号–服务器端

(3).通过SendTo()方法向指定主机发送消息(需提供主机IP地址及端口)

(4).通过ReciveFrom()方法接收指定主机发送的消息(需提供主机IP地址及端口)
    在这里插入图片描述

1、服务端

using System;
using System.Collections.Generic;
using System.Text;
#region 命名空间
using System.Net;
using System.Net.Sockets;
using System.Threading;
#endregionnamespace SocketServerConsole
{class Program{#region 控制台主函数/// <summary>/// 控制台主函数/// </summary>/// <param name="args"></param>static void Main(string[] args){//主机IPIPEndPoint serverIP = new IPEndPoint(IPAddress.Parse("192.168.1.105"), 8686);Console.WriteLine("请选择连接方式:");Console.WriteLine("A.Tcp");Console.WriteLine("B.Udp");ConsoleKey key;while (true){key = Console.ReadKey(true).Key;if (key == ConsoleKey.A) TcpServer(serverIP);else if (key == ConsoleKey.B) UdpServer(serverIP);else{Console.WriteLine("输入有误,请重新输入:");continue;}break;}}#endregion#region Tcp连接方式/// <summary>/// Tcp连接方式/// </summary>/// <param name="serverIP"></param>public static void TcpServer(IPEndPoint serverIP){Console.WriteLine("客户端Tcp连接模式");Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);tcpServer.Bind(serverIP);tcpServer.Listen(100);Console.WriteLine("开启监听...");new Thread(() =>{while (true){try{TcpRecive(tcpServer.Accept());}catch (Exception ex){Console.WriteLine(string.Format("出现异常:{0}", ex.Message));break;}}}).Start();Console.WriteLine("\n\n输入\"Q\"键退出。");ConsoleKey key;do{key = Console.ReadKey(true).Key;} while (key != ConsoleKey.Q);tcpServer.Close();}public static void TcpRecive(Socket tcpClient){new Thread(() =>{while (true){byte[] data = new byte[1024];try{int length = tcpClient.Receive(data);}catch (Exception ex){Console.WriteLine(string.Format("出现异常:{0}", ex.Message));break;}Console.WriteLine(string.Format("收到消息:{0}", Encoding.UTF8.GetString(data)));string sendMsg = "收到消息!";tcpClient.Send(Encoding.UTF8.GetBytes(sendMsg));}}).Start();}#endregion#region Udp连接方式/// <summary>/// Udp连接方式/// </summary>/// <param name="serverIP"></param>public static void UdpServer(IPEndPoint serverIP){Console.WriteLine("客户端Udp模式");Socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);udpServer.Bind(serverIP);IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);EndPoint Remote = (EndPoint)ipep;new Thread(() =>{while (true){byte[] data = new byte[1024];try{int length = udpServer.ReceiveFrom(data, ref Remote);//接受来自服务器的数据}catch (Exception ex){Console.WriteLine(string.Format("出现异常:{0}", ex.Message));break;}Console.WriteLine(string.Format("{0} 收到消息:{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Encoding.UTF8.GetString(data)));string sendMsg = "收到消息!";udpServer.SendTo(Encoding.UTF8.GetBytes(sendMsg), SocketFlags.None, Remote);}}).Start();Console.WriteLine("\n\n输入\"Q\"键退出。");ConsoleKey key;do{key = Console.ReadKey(true).Key;} while (key != ConsoleKey.Q);udpServer.Close();}#endregion}
}

2、客户端

using System;
using System.Collections.Generic;
using System.Text;
#region 命名空间
using System.Net.Sockets;
using System.Net;
using System.Threading;
#endregionnamespace SocketClientConsole
{class Program{#region 控制台主函数/// <summary>/// 控制台主函数/// </summary>/// <param name="args"></param>static void Main(string[] args){//主机IPIPEndPoint serverIP = new IPEndPoint(IPAddress.Parse("192.168.1.77"), 8686);Console.WriteLine("请选择连接方式:");Console.WriteLine("A.Tcp");Console.WriteLine("B.Udp");ConsoleKey key;while (true){key = Console.ReadKey(true).Key;if (key == ConsoleKey.A) TcpServer(serverIP);else if (key == ConsoleKey.B) UdpClient(serverIP);else{Console.WriteLine("输入有误,请重新输入:");continue;}break;}}#endregion#region Tcp连接方式/// <summary>/// Tcp连接方式/// </summary>/// <param name="serverIP"></param>public static void TcpServer(IPEndPoint serverIP){Console.WriteLine("客户端Tcp连接模式");Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);try{tcpClient.Connect(serverIP);}catch (SocketException e){Console.WriteLine(string.Format("连接出错:{0}", e.Message));Console.WriteLine("点击任何键退出!");Console.ReadKey();return;}Console.WriteLine("客户端:client-->server");string message = "我上线了...";tcpClient.Send(Encoding.UTF8.GetBytes(message));Console.WriteLine(string.Format("发送消息:{0}", message));new Thread(() =>{while (true){byte[] data = new byte[1024];try{int length = tcpClient.Receive(data);}catch (Exception ex){Console.WriteLine(string.Format("出现异常:{0}", ex.Message));break;}Console.WriteLine(string.Format("{0} 收到消息:{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Encoding.UTF8.GetString(data)));}}).Start();Console.WriteLine("\n\n输入\"Q\"键退出。");ConsoleKey key;do{key = Console.ReadKey(true).Key;} while (key != ConsoleKey.Q);tcpClient.Close();}#endregion#region Udp连接方式/// <summary>/// Udp连接方式/// </summary>/// <param name="serverIP"></param>public static void UdpClient(IPEndPoint serverIP){Console.WriteLine("客户端Udp模式");Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);string message = "我上线了...";udpClient.SendTo(Encoding.UTF8.GetBytes(message), SocketFlags.None, serverIP);Console.WriteLine(string.Format("发送消息:{0}", message));IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);EndPoint Remote = (EndPoint)sender;new Thread(() =>{while (true){byte[] data = new byte[1024];try{int length = udpClient.ReceiveFrom(data, ref Remote);//接受来自服务器的数据}catch (Exception ex){Console.WriteLine(string.Format("出现异常:{0}", ex.Message));break;}Console.WriteLine(string.Format("{0} 收到消息:{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Encoding.UTF8.GetString(data)));}}).Start();Console.WriteLine("\n\n输入\"Q\"键退出。");ConsoleKey key;do{key = Console.ReadKey(true).Key;} while (key != ConsoleKey.Q);udpClient.Close();}#endregion}
}

Tcp协议下通讯效果如下图:

客户端:
  在这里插入图片描述
服务器端:
在这里插入图片描述
基于Udp协议下通讯效果如下图:

客户端:在这里插入图片描述
服务器端:
在这里插入图片描述

总结

Tcp协议相对通讯来说相对可靠,信息不易丢失,Tcp协议发送消息,发送失败时会重复发送消息等原因。所以对于要求通讯安全较高的程序来说,选择Tcp协议的通讯相对合适。Upd协议通讯个人是比较推荐的,占用资源小,低延时,响应速度快。至于可靠性是可以通过一些应用层加以封装控制得到相应的满足。


http://www.ppmy.cn/news/1522889.html

相关文章

HiveServer2 启动时 datanucleus.schema.autoCreateTables 不生效的问题

HiveServer2 启动时出 "Either your MetaData is incorrect, or you need to enable "datanucleus.schema.autoCreateTables"问题 Required table missing : "FUNCS" in Catalog "" Schema "". DataNucleus requires this table…

深入探索Go语言中的指针:内存操作的艺术

首先&#xff0c;尽管指针&#xff08;pointer&#xff09;和switch语句在概念上并无直接联系&#xff0c;但本文将它们并置讨论的原因在于&#xff1a;这两个编程概念在实际学习和应用过程中常被编程人员所忽视。 对于指针的使用&#xff0c;初学者往往因其概念的抽象性和操作…

探索Oracle数据库的多租户特性:架构、优势与实践

在云计算和大数据时代&#xff0c;多租户架构成为数据库设计中的一个重要趋势。Oracle数据库的多租户选项&#xff08;Multitenant&#xff09;允许单个数据库实例支持多个独立数据库&#xff08;称为容器数据库和可插拔数据库&#xff09;&#xff0c;每个数据库都有自己的数据…

Vue3:<Teleport>传送门组件的使用和注意事项

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 Vue3 引入了一个新的内置组件 <Teleport>&#xff0c;它允许你将子组件树渲染到 DOM 中的另一个位置&#xff0c;而不是在父组件的模板中直接渲染。这对于需要跳出当前组件的 DOM 层级结构进行渲染的…

算法:判断一个整数是不是2的阶次方

一、思路 核心&#xff1a;不断除以2&#xff0c;缩小判断的范围 判断整数除以2的余数是否为0&#xff0c;如果不为0&#xff0c;则直接返回false&#xff1b;如果为0&#xff0c;则将将整数除以2后重复本步骤。 注意&#xff1a; 1为2的0次幂。 二、代码 public class Numb…

第十章 【后端】环境准备(10.2)——Maven

10.2 Maven Maven 官网:https://maven.apache.org/ Maven 仓库:https://mvnrepository.com/ 下载 解压 在非系统盘上创建仓库目录 如:E:\maven-repository 修改配置 配置文件为 Maven 目录的 conf\settings.xml,修改为: <?xml version="1.0" encoding=&qu…

25版王道数据结构课后习题详细分析 第八章 8.5 归并排序、基数排序和计数排序

一、单项选择题 ———————————————————— ———————————————————— 解析&#xff1a;我们知道插入排序不能保证在一趟排序结束后一定有元素放在最终位置上。事实上&#xff0c;归并排序也不能保证。例如&#xff0c;序列{6,5,7,8,2,1,4,3}…

【Linux 从基础到进阶】Redis缓存服务安装与调优

Redis缓存服务安装与调优 引言 Redis 是一个开源的内存数据结构存储系统,广泛应用于缓存、会话管理和实时分析等场景。它支持多种数据结构,如字符串、哈希、列表、集合和有序集合,因其高性能和灵活性,成为开发者的首选缓存解决方案。本文将介绍如何在 CentOS 和 Ubuntu 系…

Python | Leetcode Python题解之第387题字符串中的第一个唯一字符

题目&#xff1a; 题解&#xff1a; class Solution:def firstUniqChar(self, s: str) -> int:position dict()q collections.deque()n len(s)for i, ch in enumerate(s):if ch not in position:position[ch] iq.append((s[i], i))else:position[ch] -1while q and po…

Kubernetes学习指南:保姆级实操手册05——配置集群HA负载均衡

五、Kubernetes学习指南&#xff1a;保姆级实操手册05——配置集群HA负载均衡 简介&#xff1a; Keepalived 提供 VRRP 实现&#xff0c;并允许您配置 Linux 机器使负载均衡&#xff0c;预防单点故障。HAProxy 提供可靠、高性能的负载均衡&#xff0c;能与 Keepalived 完美配合…

uniapp如何监听页面滚动?

在uni-app中&#xff0c;监听页面滚动主要通过在页面的.vue文件中的onPageScroll生命周期函数来实现。onPageScroll函数会在页面滚动时触发&#xff0c;你可以在这个函数中获取到当前页面的滚动位置等信息。 下面是一个简单的示例&#xff0c;展示了如何在uni-app中监听页面滚…

解决docker启动失败的错误“Status: unknown flag: --graph”

最近服务器重启以后docker启动失败了&#xff0c;使用以下命令查看 Docker 的日志文件以获取更详细的错误信息。 journalctl -u docker.service -e 9月 05 10:50:06 iZj6c94a19bsvkhti6zw6oZ dockerd[4379]: Status: unknown flag: --graph 9月 05 10:50:06 iZj6c94a19bsvkhti…

C++音视频开发笔记目录

目录 &#x1f315;基础知识&#x1f319;详解FFmpeg&#x1f319;播放音视频时发生了什么&#xff1f; & 视频的编解码 & H264是什么&#xff1f; & MP4是什么&#xff1f; &#x1f315;流媒体环境搭建&#x1f319;windows安装FFMpeg&#x1f319;docker一键部署…

Oracle SQL Developer:数据库开发与数据管理的利器

在数据库管理和开发领域&#xff0c;拥有一个强大而灵活的工具是至关重要的。Oracle SQL Developer 是 Oracle 公司提供的一个免费集成开发环境&#xff0c;它专为数据库开发、管理和数据建模而设计。本文将详细介绍 Oracle SQL Developer 的功能、特点以及如何使用它来执行数据…

面试真题 | 记录一次面试真题

一、基本问题(80%) 1、const 和 static 的作用: const(常量): 用于定义常量值,保证变量不可被修改。在函数参数中使用const可以保证函数内不会修改参数值。用于定义常量成员函数,表明该成员函数不会修改对象的状态。可以与指针一起使用,如const int*表示指针指向的值不…

单项链表的原地反转

逻辑图如下所示&#xff1a; 只需要将需要反转的节点放到头节点位置即可&#xff0c; 使用两个指针一个指针指向需要反转的节点&#xff0c;另一个指针指向需要反转的指针的前驱节点&#xff08;其实也就是元链表的头节点&#xff09; 操作过程&#xff1a; 1 2 3 4 5 2 1 …

Base x DAOBase: Base生态聚会新加坡站,共筑链上未来

备受期待的 Base 社区聚会将于新加坡 Token2049 期间盛大举行&#xff0c;这为 Base 的支持者和生态建设者们提供了一个绝佳的相聚机会。本次活动由 Base、 DAOBase以及其他合作方共同支持。Base 是全球知名交易所 Coinbase 研发的以太坊 Layer2 扩容方案&#xff0c;致力于为用…

html css js 编程简单实现 随机抽奖 练习小项目

我们经常在某些网站上 看到一些 抽奖的活动&#xff0c;比如大转盘 随机抽奖 这种抽奖程序是怎么实现的呢&#xff1f;下面分享一个代码 简单的 实现了一下 随机抽奖的逻辑 对于网页的 美观度 就不分享了 主要是分享 js怎么 随机的 让 奖品滚顶起来 然后 某个节点 停止滚动 从而…

JavaWeb后端开发总结(3)

AOP基础 AOP概述 首先我们要知道AOP是什么&#xff1f; 看下图 个人解析&#xff1a; AOP叫做面向切面编程&#xff0c;但是实际上就是面向方法编程 图中下面一部分是一个AOP的案例 AOP快速入门案例代码实现 案例&#xff1a;测出业务中各个业务方法所需的执行时间 如果…

冒泡排序算法介绍

冒泡排序算法介绍 如果真的累了&#xff0c;就拉上窗帘关上手机关掉闹钟深呼吸一口气钻进被窝&#xff0c;好好地睡一觉&#xff0c;难熬的日子总需要一些温暖&#xff0c;而什么都不如被窝的温暖来的踏实。 冒泡排序是一种经典的排序算法&#xff0c;它通过重复遍历待排序的序…