C语言用UDP 实现局域网聊天程序源码
见习无聊写的一个基于c# socket udp的简单的局域网聊天软件 含源码
![见习无聊写的一个基于c# socket udp的简单的局域网聊天软件 含源码](https://img.taocdn.com/s3/m/27a67a85dd36a32d737581bb.png)
见习无聊写的一个基于c# socket udp的简单的局域网聊天软件含源码实习无聊,写的一个基于c# socket udp的简单的局域网聊天软件含源码最后在公司实习,新人不给活干,就自己随便看看,了解一些DevExpress控件啊,编码规范啊之类的,自己就寻思着写一点点小东西练习练习出于自己对c# socket这块不熟,就选择了这块,顺便可以进一步了解委托代理。
闲话不说,先说下这次做的东西:一个局域网聊天的小软件主要基于udp的通信,如果读者还不知道udp or tcp 那请度娘一下。
直接看图吧:本机端局域网中的另一端猛击我去我的博客查看此软件的详解再猛击我去免费下载源码在软件上设计的不到之处或者源码上编写的问题之处请大家留言发帖指导啊------解决方案--------------------------------------------------------看看...------解决方案--------------------------------------------------------感觉还是不错的、。
美化美化就更好了------解决方案--------------------------------------------------------最后在公司实习,新人不给活干,就自己下载下来看看。
------解决方案--------------------------------------------------------------解决方案--------------------------------------------------------能p2p聊天不,------解决方案--------------------------------------------------------------解决方案--------------------------------------------------------------解决方案--------------------------------------------------------也学习一下吧!------解决方案--------------------------------------------------------来虚心学习------解决方案--------------------------------------------------------好好干,有前途------解决方案--------------------------------------------------------支持一下------解决方案--------------------------------------------------------还真不错! GUI做得挺像那么回事的------解决方案--------------------------------------------------------感觉还不错哦~同是新人,加油哦!------解决方案--------------------------------------------------------学习了。
C++基于socketUDP网络编程实现简单聊天室功能
![C++基于socketUDP网络编程实现简单聊天室功能](https://img.taocdn.com/s3/m/4d310640f11dc281e53a580216fc700abb6852a8.png)
C++基于socketUDP⽹络编程实现简单聊天室功能本⽂实例为⼤家分享了C++基于socket UDP实现简单聊天室功能的具体代码,供⼤家参考,具体内容如下0.通信步骤流程图(左:服务器;右:客户端;)1.服务器代码1.1服务器类头⽂件(CServer_UDP.h)#pragma once#include <winsock2.h>class CServer_UDP{public:CServer_UDP();void SendMsg(const char sendBuf[]);void RecMsg();~CServer_UDP();private:SOCKET m_sServer;struct sockaddr_in m_SocAddrClient; //建⽴连接时,⽤于保存客户端信息bool m_terminal;};1.2服务器类源⽂件(CServer_UDP.cpp)#define _WINSOCK_DEPRECATED_NO_WARNINGS#include "CServer_UDP.h"#include <iostream>#pragma comment(lib, "ws2_32.lib")CServer_UDP::CServer_UDP():m_terminal(false){//必须进⾏如下初始化,否则socket()会返回10093错误//初始化WSAWORD sockVersion = MAKEWORD(2, 2);WSADATA wsaData;if (WSAStartup(sockVersion, &wsaData) != 0) //通过⼀个进程初始化ws2_32.dll{std::cout << "Initialize WSA failed" << std::endl;return;}//初始化UDDP套接字m_sServer = socket(AF_INET, SOCK_DGRAM, 0);struct sockaddr_in m_SocAddrserver;m_SocAddrserver.sin_addr.S_un.S_addr = 0;//htonl(INADDR_ANY);m_SocAddrserver.sin_family = AF_INET;m_SocAddrserver.sin_port = htons(8090);int ret = bind(m_sServer, (sockaddr*)&m_SocAddrserver, sizeof(m_SocAddrserver));if (ret == -1){std::cout << "bind failed!" << std::endl;WSACleanup();}else{//此处必须赋初值,不然会导致服务器端⽆法正常发送int len_Client = sizeof(sockaddr);char recBuf[1025];int len = recvfrom(m_sServer, recBuf, 1024, 0, (sockaddr*)&m_SocAddrClient, &len_Client);if (len > 0){recBuf[len] = '\0';std::cout << "Client say:" << recBuf << std::endl;}}}void CServer_UDP::SendMsg(const char sendBuf[]){int ret = sendto(m_sServer, sendBuf, strlen(sendBuf), 0, (sockaddr*)&m_SocAddrClient, sizeof(m_SocAddrClient)); if (ret == -1){std::cout << "send failed" << std::endl;std::cout << GetLastError()<< std::endl;}}void CServer_UDP::RecMsg(){char recBuf[1025];while (!m_terminal){//std::cout << "Begin rec...(server)" << std::endl;int len = recvfrom(m_sServer, recBuf, 1024, 0, 0, 0);if (len > 0){recBuf[len] = '\0';std::cout << "Client say:" << recBuf << std::endl;}}}CServer_UDP::~CServer_UDP(){closesocket(m_sServer);WSACleanup();}1.3服务器主函数#include <iostream>#include <thread>#include <string>#include "CServer_UDP.h"using namespace std;int main(){CServer_UDP server_UDP;thread recProc(&CServer_UDP::RecMsg, &server_UDP);while (1){//cout << "Pleaes input content:" << endl;string content;cin >> content;server_UDP.SendMsg(content.c_str());}recProc.join();cout << "I love china!" << endl;system("pause");return 0;}2.客户端代码2.1客户端类头⽂件(CClient.h)#pragma once#include <winsock2.h>class CClient{public:CClient();void RecMsg();void SendMsg(const char sendBuf[]);~CClient();private:SOCKET m_sockClient;sockaddr_in m_TargetServer;};2.2客户端类源⽂件(CClient.cpp)#define _WINSOCK_DEPRECATED_NO_WARNINGS#include "CClient.h"#include <iostream>#pragma comment(lib, "ws2_32.lib")CClient::CClient(){//必须进⾏如下初始化,否则socket()会返回10093错误//初始化WSAWORD sockVersion = MAKEWORD(2, 2);WSADATA wsaData;if (WSAStartup(sockVersion, &wsaData) != 0) //通过⼀个进程初始化ws2_32.dll{std::cout << "Initialize WSA failed" << std::endl;return;}m_sockClient = socket(AF_INET, SOCK_DGRAM, 0);m_TargetServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");m_TargetServer.sin_family = AF_INET;m_TargetServer.sin_port = htons(8090);if (m_sockClient == -1){std::cout << "Create socket failed!" << std::endl;WSACleanup();}else{//发送信息与服务器建⽴连接(必须加)sendto(m_sockClient, "hello server", strlen("hello server"), 0, (sockaddr*)&m_TargetServer, sizeof(m_TargetServer)); }}void CClient::SendMsg(const char sendBuf[]){sendto(m_sockClient, sendBuf, strlen(sendBuf), 0, (sockaddr*)&m_TargetServer, sizeof(m_TargetServer));}void CClient::RecMsg(){char recBuf[1025];while (1){//std::cout << "Begin rec...(client)" << std::endl;int len = recvfrom(m_sockClient, recBuf, 1024, 0, 0, 0);if (len > 0){recBuf[len] = '\0';std::cout << "Server say: " << recBuf << std::endl;}}}CClient::~CClient(){closesocket(m_sockClient);WSACleanup();}2.3客户端主函数#include <iostream>#include <string>#include <thread>#include "CClient.h"using namespace std;int main(){CClient client_UDP;thread RecProc(&CClient::RecMsg, &client_UDP); while (1){//cout << "Please input content:" << endl;string content;cin >> content;client_UDP.SendMsg(content.c_str());}RecProc.join();cout << "I love china!" << endl;system("pause");return 0;}3.效果图(win7+VS2017)3.1服务端3.2客户端以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
用C开发局域网聊天工具
![用C开发局域网聊天工具](https://img.taocdn.com/s3/m/fb8efe523186bceb19e8bbd5.png)
用Socket开发局域网聊天工具(C#)程序设计成为简单的服务端和客户端之间的通信,但通过一些方法可以将这两者进行统一起来,让服务端也成为客户端,让客户端也成为服务端,使它们之间可以互相随时不间断的通信.考虑到实现最原始的服务端和客户端之间的通信所需要的步骤对于写这样的程序是很有帮助的.作为服务端,要声明一个SocketA并绑定(Bind)某一个IP+这个IP指定的通信端口,比如这个是127.0.0.1:9050,然后开始监听(Listen), Listen可以监听来自多个IP传过来的连接请求,具体可以同时连接几个客户端,Listen方法中可以设定一个参数.如果Listen到某一个客户端发来连接请求了,这时定义一个新的SocketB专门负责与这个客户端的通信,SocketB=A.Accept().这时可以获取这个客户端的IP和端口, IPEndPoint C =(IPEndPoint)B.RemoteEndPoint, C.Address和C.Port分别表示客户端C的IP地址和端口.这时通过B.Send()方法就可以给C发送消息了,B.Receive()可以接收客户端C发来的信息.作为客户端,也需要声明一个Socket D并绑定某一个IP+本机一个未被占用的端口,定义IPEndPointE表示要进行连接的服务端Socket,要指明E的IP和端口,这样才可以进行端口对端口之间的通信,接下来就可以尝试D.Connect(E),连接成功之后就可以发送和接收数据了,D.Send(),D.Receive.发送消息时,数据都是以字节或字节数组为单位进行传输的,比如我客户端D要发送"Hello World"则要这样写:D.Send(Encoding.ASCII.GetBytes("Hello World")).接受消息时,也是以字节或字节数组,比如服务端要接受D刚才发送的Hello World,可以这样写:Byte[] data = new Byte[1024]; int receivedDataLength = B.Receive(data);string stringdata = Encoding.ASCII.GetString(data, 0,receivedDataLength); stringdata这时就是Hello World.上面只是大概的阐述了服务端与客户端之间的通信过程,在网上找到了具体的代码例子,也贴过来参考参考.这个例子没有将服务端与客户端统一起来,他是分别写服务端和客户端的.服务端:using System;using System;using ;using .Sockets;using System.Text;namespace tcpserver{/// <summary>/// Class1的摘要说明。
C#使用UDP Client编写聊天程序
![C#使用UDP Client编写聊天程序](https://img.taocdn.com/s3/m/28353ffcfab069dc50220164.png)
★C#使用UDP Client编写聊天程序UDPClient 类使用UDP 与网络服务通讯。
UDP 的优点是简单易用,并且能够同时向多个地址广播消息。
但由于UDP 协议是一个无连接协议,因此发送到远程终结点的UDP 数据文报不一定能够到达,也不一定能够以发送的相同顺序到达。
使用UDP 的应用程序必须准备处理丢失的和顺序有误的数据文报。
若要使用UDP 发送数据文报,必须知道承载所需服务的网络设备的网络地址以及该服务用于通讯的UDP 端口号。
特殊网络地址用于支持基于IP 的网络上的UDP 广播消息。
下面探讨的内容以Internet 上使用的IP 版本4 地址族作为示例。
IP 版本4 地址使用32 位指定网络地址。
对于使用255.255.255.0 网络掩码的C 类地址,这些位被分为四个八位字节。
当以十进制数表示时,这四个八位字节构成熟悉的以点分隔的四部分表示法,如192.168.100.2。
前两个八位字节(此示例中为192.168)构成网络号;第三个八位字节(100) 定义子网;最后一个八位字节(2) 是主机标识符。
将IP 地址的所有位均设置为1(即255.255.255.255)可构成有限的广播地址。
将UDP 数据文报发送到此地址可将消息传递到该广播网络上的任何主机。
由于路由器从不转发发送到此地址的消息,因此只有已连接的网络上的主机才可看到这些广播。
通过将部分地址的所有位全都设置为1,可以将广播定向到特定的网络部分。
例如,若要将广播发送到以192.168 打头的IP 地址标识的网络上的所有主机,请将地址的子网和主机部分全都设置为1,如192.168.255.255。
若要将广播限制在单个子网,则只将主机部分设置全都为1,如192.168.100.255。
UdpClient 类可向任何网络广播地址广播,但它无法侦听发送到网络的广播。
必须使用Socket 类才能侦听网络广播。
当所有接收者都位于单个网络中时,或者当许多客户端需要接收广播时,广播地址将起作用。
计算机毕业设计85UDP局域网QQ聊天程序设计说明书
![计算机毕业设计85UDP局域网QQ聊天程序设计说明书](https://img.taocdn.com/s3/m/3220bbfaba0d4a7302763ad8.png)
摘要随着网络技术的发展及人们生活的需求,网络聊天已越来越受到人们的青睐。
网络聊天已经成为人们工作生活中传递信息、交流感情的重要工具,给人们带来了很大的方便。
本设计开发的是一个局域网QQ聊天软件,运用软件工程的设计流程,使用现在比较普遍和流行的C#语言,采用面向对象的方法,综合运用数据库编程技术、多线程开发技术、网络通讯技术,以Microsoft Visual Studio 2005作为系统前台应用程序开发工具,Microsoft SQL Server 2000作为后台数据库管理系统,在Windows XP平台下进行开发。
本局域网QQ聊天软件采用服务器端/客户端(C/S)模式。
客户端采用UDP与服务器连接,客户端之间也是通过UDP互相通讯。
服务器端主要用于开启和关闭UDP协议的监听服务,还可以查看局域网内已注册的所有的用户以及他们的在线状态。
客户端分为注册窗口、登录窗口、QQ窗体主界面以及聊天界面。
服务器端要先开启监听服务,客户端才可以进行登录,然后才可以与其他登录的在线用户进行文本信息的聊天,还可以进行点对点的语音聊天,视频聊天和文件传输,还可以进行拍照和录像等。
此外,还对该软件进行了皮肤的加载以及打包成安装源。
该软件运行稳定,界面美观、操作简便。
在局域网内部使用该局域网QQ聊天软件,可以方便人与人之间的沟通、交流;可以大大提高企业的工作效率;拉近人与人之间的关系。
关键词:局域网;聊天软件;客户端;服务器端;UDP协议AbstractWith the development of networking technology and the living demand of people, chatting on network is more and more acceptable by people. Internet chat has become an important tool to transmission of information and exchange of feelings in our life, it brings a great convenience.The topic of this paper is going to talk about that to develop the local area network QQ chat software. This local area network chat software using the design stream of the software project, using the C# language which is very common and popular, using the object-oriented approach, the technology of the database programming, multi-threading development technology and the network communication technology, makes Microsoft Visual Studio 2005 as the front application design tool, Microsoft SQL Server 2000 are used as the background DBMS( the database management system ), and it was programmed in the Windows XP System.The local area network QQ chat software uses the server and client (C/S) mechanism. And the client connects the server using UDP, and they communicate each other by UDP. Server-side is mainly used to open and close the UDP protocol monitoring service, and you can also look over all the registered users and their online status whom in the local area network. Client is divided into registration window, the login window, the main QQ form and the chat form. If the client wants to log in, the server monitoring service must first open the listening service, then the client can chat with the others which have already logged, and also can voice chat, video chat and files transfers, and also can take pictures and videos. In addition, the software has been load the beautiful skin and package into the installation source.This software has an interface aesthetics, stable operation, simple operation. Using QQ software in the LAN internal can help people to communicate with others easily, can greatly improve the efficiency of the enterprises, close relationships between people.Key Words: Local Area Network; Chat Software; Client; Server-side; UDP protocol目录引言 (1)1系统概述与需求分析 (2)1.1 系统概述 (2)1.2 需求分析 (2)1.2.1功能需求 (3)1.2.2性能需求 (3)1.3 可行性分析 (4)2 系统总体设计 (5)2.1 相关开发技术的原理性说明 (5) Framework和C# (5)2.1.2SQL Server 2005 (6)2.1.3UDP协议简介 (6)2.1.4Socket简介 (6)2.2 系统功能结构 (7)2.3 业务流程图 (8)2.4 程序运行环境 (8)3 数据库以及类库的详细设计与实现 (9)3.1 数据库的创建 (9)3.1.1数据库分析 (9)3.1.2数据库创建 (9)3.1.3数据库概念设计 (9)3.1.4数据库逻辑结构设计 (9)3.1.5文件夹组织结构 (10)3.2 类库的设计 (10)4 客户端模块的详细设计及实现 (12)4.1客户端注册模块的设计 (12)4.1.1客户端注册模块概述 (12)4.1.2客户端注册模块技术分析 (13)4.1.3客户端注册模块实现过程 (13)4.2 客户端登陆模块设计 (14)4.2.1客户端登陆模块概述 (14)4.2.2客户端登陆模块技术分析 (14)4.2.3客户端登陆模块实现过程 (14)4.3 客户端QQ模块设计 (15)4.3.1客户端QQ模块概述 (15)4.3.2客户端QQ模块技术分析 (15)4.3.3客户端QQ模块实现过程 (16)4.4 客户端消息发送模块设计 (17)4.4.1客户端消息发送模块概述 (17)4.4.2客户端消息发送模块技术分析 (18)4.4.3客户端消息发送模块实现过程 (18)5 服务器端模块的详细设计与实现 (23)5.1 服务器端控制台窗体概述 (23)5.2 服务器端控制台窗体技术分析 (23)5.3 服务器端控制台窗体实现过程 (23)6 系统特色及关键技术 (24)7 结论 (25)谢辞 (28)参考文献 (29)附录 (30)引言在Internet飞速发展的今天,互联网成为人们快速获取、发布和传递信息的重要渠道,它在人们政治、经济、生活等各个方面发挥着重要的作用。
局域网聊天软件源代码包括语音聊天
![局域网聊天软件源代码包括语音聊天](https://img.taocdn.com/s3/m/a68317f59e314332396893f0.png)
局域网聊天软件源代码包括语音聊天// Chat.h : PROJECT_NAME 应用程序的主头文件//#pragma once#ifndef __AFXWIN_H__#error "在包含此文件之前包含“stdafx.h”以生成PCH 文件" #endif#include "resource.h" // 主符号// CChatApp:// 有关此类的实现,请参阅Chat.cpp//class CChatApp : public CWinApp{public:CChatApp();// 重写public:virtual BOOL InitInstance();// 实现DECLARE_MESSAGE_MAP()};extern CChatApp theApp;// Chat.cpp : 定义应用程序的类行为。
//#include "stdafx.h"#include "Chat.h"#include "ChatDlg.h"//#ifdef _DEBUG//#define new DEBUG_NEW// CChatAppBEGIN_MESSAGE_MAP(CChatApp, CWinApp)ON_COMMAND(ID_HELP, &CWinApp::OnHelp)END_MESSAGE_MAP()// CChatApp 构造CChatApp::CChatApp(){// TODO: 在此处添加构造代码,// 将所有重要的初始化放置在InitInstance 中}// 唯一的一个CChatApp 对象CChatApp theApp;// CChatApp 初始化BOOL CChatApp::InitInstance(){// 如果一个运行在Windows XP 上的应用程序清单指定要// 使用ComCtl32.dll 版本6 或更高版本来启用可视化方式,//则需要InitCommonControlsEx()。
(精品)UDP局域网聊天室实现
![(精品)UDP局域网聊天室实现](https://img.taocdn.com/s3/m/0466ff91172ded630a1cb619.png)
} msg_t;
分析函数实现:
服务器端:
1.int send_assign_client(int serfd,Linklist *head,msg_t *pmsg); 功能:
通过名字查找对应的客户端是否存在,存在则发送消息 不存在返回出错信息表示客户端不存在
那么我们分析一下该链表的数据结构构建。 数据结构 地址信息节点:
typedef struct node { struct sockaddr_in addr; struct node *next;
} data_t;
//消息类型
#define CLIENT_TALK 100 #define SERVER_TALK 200
分析客户端的流程:
客户端: 整体的流程首先是 网络的基本编程
socket pid = fork(); if (pid > 0) //父进程,主要功能,数据发送 {
while (1) { //大循环 1.发送一个登录的消息,告诉大家我上线了 2..从键盘获得数据 a.聊天的对端的名字 SYSTERM 群聊消息 非SYSTERM 私聊消息 c.聊天的内容 d.输入quit时,结束 3.聊天结束,发送一个聊天结束的消息给大家,告诉大家说我下线了
/* See NOTES */
} } } else if (pid == 0)//子进程,主要功能,数据接收 {
while (1) { 1.接收数据 2.显示数据
}
}
分析"服务器端"的流程:
整体的流程是 UDP的网络服务器的 基本编程
socket bind pid = fork(); if (pid >0)//父进程 发数据,系统级别的消息,给所有客户端发送消息 {
VC++之网络编程五聊天编程实例(UDP)
![VC++之网络编程五聊天编程实例(UDP)](https://img.taocdn.com/s3/m/5da108aef021dd36a32d7375a417866fb84ac0c6.png)
VC++之⽹络编程五聊天编程实例(UDP)Server:#include <Winsock2.h>#include <stdio.h>void main(){//mide delete wordWORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0){return;}if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wHighVersion)!=2){WSACleanup();return ;}SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));char recvBuf[100];char sendBuf[100];char tempBuf[100];SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);while(1){recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);if('q'==recvBuf[0]){sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len);printf("chat end!/n");break;}sprintf(tempBuf,"%s say: %s",inet_ntoa(addrClient.sin_addr),recvBuf);printf("%s/n",tempBuf);printf("Please input data:/n");gets(sendBuf);sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len);}closesocket(sockSrv);WSACleanup();}client:#include <Winsock2.h>#include <stdio.h>void main(){//mide delete wordWORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0){return;}if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wHighVersion)!=2){WSACleanup();return ;}SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);sendto(sockClient,"Hello",strlen("Hello")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));closesocket(sockClient);WSACleanup();}注意:server 和 client 都要"项⽬属性"--->"配置属性"----> "链接"----> "输⼊" --->"附加依赖项"中添加"ws2_32.lib"。
局域网聊天程序作品+源代码
![局域网聊天程序作品+源代码](https://img.taocdn.com/s3/m/7cc3d38583d049649b6658d7.png)
文章标题:[原创]局域网聊天程序作品+源代码顶部 goldberg 发布于:2006-05-2415:45 [楼主][原创]局域网聊天程序作品+源代码
软件作者:Goldberg[安全矩阵]()
信息来源:邪恶八进制信息安全团队()
注意:此软件首发于安全矩阵()后由原创作者友情提交到邪恶八进制信息安全团队
用VB个做了局域网聊天的小软件,做的很垃圾,界面更是丑陋无比(自己只是个编程小菜鸟),现在发到论坛上丢人现眼一下,同时也请各位高手不吝赐教,谢谢.
六一儿童节快到了,祝天程序的作品+源代码
附件二是UDP协议下局域网聊天程序的作品+源代码
描述:TCP协议下局域网聊天程序的作品+源代码
附件:TCP实现局域网聊天.rar(15K)下载次数:302
描述:UDP协议下局域网聊天程序的作品+源代码
附件:UDP实现局域网聊天.rar(31K)下载次数:175(c)Copyleft2003-2007,EvilOctalSecurityTeam.
ThisfileisdecompiledbyanunregisteredversionofChmDecompiler.
Regsiteredversiondoesnotshowthismessage.
YoucandownloadChmDecompilerat:/
C基于UDP实现一个简易的聊天室
![C基于UDP实现一个简易的聊天室](https://img.taocdn.com/s3/m/f00d4e0eb42acfc789eb172ded630b1c59ee9b88.png)
C基于UDP实现⼀个简易的聊天室引⾔ 本⽂是围绕Linux udp api 构建⼀个简易的多⼈聊天室.重点看思路,帮助我们加深对udp开发中⼀些api了解.相对⽽⾔udp socket开发相⽐tcp socket开发注意的细节要少很多.但是⽔也很深. 本⽂就当是⼀个demo整合帮助开发者回顾和继续了解 linux udp开发的基本流程.⾸先我们来看看 linux udp 和 tcp的异同./*这⾥简单⽐较⼀下TCP和UDP在编程实现上的⼀些区别:TCP流程建⽴⼀个TCP连接需要三次握⼿,⽽断开⼀个TCP则需要四个分节。
当某个应⽤进程调⽤close(主动端)后(可以是服务器端,也可以是客户端),这⼀端的TCP发送⼀个FIN,表⽰数据发送完毕;另⼀端(被动端)发送⼀个确认,当被动端待处理的应⽤进程都处理完毕后,发送⼀个FIN到主动端,并关闭套接⼝,主动端接收到这个FIN后再发送⼀个确认,到此为⽌这个TCP连接被断开。
UDP套接⼝ UDP套接⼝是⽆连接的、不可靠的数据报协议;既然他不可靠为什么还要⽤呢? 其⼀:当应⽤程序使⽤⼴播或多播是只能使⽤UDP协议; 其⼆:由于它是⽆连接的,所以速度快。
因为UDP套接⼝是⽆连接的,如果⼀⽅的数据报丢失,那另⼀⽅将⽆限等待,解决办法是设置⼀个超时。
在编写UDP套接⼝程序时,有⼏点要注意:建⽴套接⼝时socket函数的第⼆个参数应该是SOCK_DGRAM,说明是建⽴⼀个UDP套接⼝;由于UDP是⽆连接的,所以服务器端并不需要listen或accept函数;当UDP套接⼝调⽤connect函数时,内核只记录连接放的IP地址和端⼝,并⽴即返回给调⽤进程.*/参照/wocjj/article/details/8315559/Jessy/p/3536163.html这⾥简单引述⼀下 udp相⽐tcp ⽤到的两个api . recvfrom()/sendto() 具体细节如下#include <sys/types.h>#include <sys/socket.h>/** 这两个函数基本等同于⼀个 send 和 recv . 详细参数解释如下* s : ⽂件描述符,等同于 socket返回的值* buf : 数据其实地址* len : 发送数据长度或接受数据缓冲区最⼤长度* flags : 发送标识,默认就⽤O.带外数据使⽤ MSG_OOB, 偷窥⽤MSG_PEEK .....* addr : 发送的⽹络地址或接收的⽹络地址* alen : sento标识地址长度做输⼊参数, recvfrom表⽰输⼊和输出参数.可以为NULL此时addr也要为NULL* : 返回0表⽰执⾏成功,否则返回<0 . 更多细节查询man⼿册*/extern int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *addr, int alen);extern int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *addr, int *alen);上⾯就是两个函数的⼤致⽤法. 具体可以查看linux api帮助⼿册. 最好就⽤ man sendto / man recvfrom 把那⼀系列函数都看看.现在很多⽂章都是转载,但是找不见转载的地址, 下⾯会举⼀个简易的UDP回显服务器的demo加深理解.前⾔⾸先看设计图有点low. 简单看看吧. 那我们先看客户端代码 udpclt.c 代码#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define _SHORT_PORT (8088)//// udp client heoo//int main(int argc, char * argv[]) {int fd, len;struct sockaddr_in ar = { AF_INET };socklen_t al = sizeof (struct sockaddr_in);char msg[BUFSIZ] = ":) 谁也不会喜欢⼯作狂 ~";// 创建 client socketif ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {perror("main socket dgram");exit(EXIT_FAILURE);}ar.sin_port = htons(_SHORT_PORT);// 开始发送消息包到服务器, 默认⾛ INADDR_ANYsendto(fd, msg, sizeof msg - 1, 0, (struct sockaddr *)&ar, al);// 开始接收服务器回过来的报⽂len = recvfrom(fd, msg, sizeof msg - 1, 0, (struct sockaddr *)&ar, &al);if (len == -1) {perror("main recvfrom");exit(EXIT_FAILURE);}msg[len] = '\0';printf("[%s:%hd] -> %s\n", inet_ntoa(ar.sin_addr), ntohs(ar.sin_port), msg); // 程序结束return close(fd);}编译是gcc -g -Wall -o udpclt.out udpclt.cudp 服务器 udpsrv.c#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define _SHORT_PORT (8088)//// udp server heoo//int main(int argc, char * argv[]) {int fd, len;struct sockaddr_in ar = { AF_INET };socklen_t al = sizeof (struct sockaddr_in);char msg[BUFSIZ];if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {perror("main socket dgram");exit(EXIT_FAILURE);}printf("udp server start [%d][0.0.0.0][%hd] ...\n", fd, _SHORT_PORT);// 服务器绑定地址ar.sin_port = htons(_SHORT_PORT);if (bind(fd, (struct sockaddr *)&ar, al) == -1) {perror("main bind INADDR_ANY");exit(EXIT_FAILURE);}// 阻塞的接收不同客户端数据来回搞while ((len = recvfrom(fd, msg, sizeof msg - 1, 0, (struct sockaddr *)&ar, &al)) > 0) {msg[len] = '\0';printf("[%s:%hd] -> %s\n", inet_ntoa(ar.sin_addr), ntohs(ar.sin_port), msg);// 回显继续发送给客户端sendto(fd, msg, len, 0, (struct sockaddr *)&ar, al);}return close(fd);}编译是gcc -g -Wall -o udpsrv.out udpsrv.c后⾯运⾏结果如下 udp服务器如下 (Ctrl + C 退出)udp 客户端如下(修改了⼀版本, 当前版本更加简单, 容易理解.)到这⾥将上⾯代码敲⼀遍基本上 udp ⼀套 api 就会使⽤了. 后⾯进⼊正题设计聊天室代码.正⽂ ⾸先看客户端设计代码. 主要思路是⼦进程处理数据的输出, ⽗进程处理服务器数据的接收. 具体设计如下(画的图有点low就不画了.../(ㄒo ㄒ)/~~)udpmulclt.c#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <signal.h>#include <sys/wait.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>// 名字长度包含'\0'#define _INT_NAME (64)// 报⽂最⼤长度,包含'\0'#define _INT_TEXT (512)//4.0 控制台打印错误信息, fmt必须是双引号括起来的宏#define CERR(fmt, ...) \fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\__FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__)//4.1 控制台打印错误信息并退出, t同样fmt必须是 ""括起来的字符串常量#define CERR_EXIT(fmt,...) \CERR(fmt,##__VA_ARGS__),exit(EXIT_FAILURE)/** 简单的Linux上API错误判断检测宏, 好⽤值得使⽤*/#define IF_CHECK(code) \if((code) < 0) \CERR_EXIT(#code)// 发送和接收的信息体struct umsg{char type; //协议 '1' => 向服务器发送名字, '2' => 向服务器发送信息, '3' => 向服务器发送退出信息char name[_INT_NAME]; //保存⽤户名字char text[_INT_TEXT]; //得到⽂本信息,空间换时间};/** udp聊天室的客户端, ⼦进程发送信息,⽗进程接受信息*/int main(int argc, char* argv[]) {int sd, rt;struct sockaddr_in addr = { AF_INET };socklen_t alen = sizeof addr;pid_t pid;struct umsg msg = { '1' };// 这⾥简单检测if(argc != 4) {fprintf(stderr, "uage : %s [ip] [port] [name]\n", argv[0]);exit(-1);}// 下⾯对接数据if((rt = atoi(argv[2]))<1024 || rt > 65535)CERR("atoi port = %s is error!", argv[2]);// 接着判断ip数据IF_CHECK(inet_aton(argv[1], &addr.sin_addr));addr.sin_port = htons(rt);// 这⾥拼接⽤户名字strncpy(, argv[3], _INT_NAME - 1);//创建socket 连接IF_CHECK(sd = socket(PF_INET, SOCK_DGRAM, 0));// 这⾥就是发送登录信息给udp聊天服务器了IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen));//开启⼀个进程, ⼦进程处理发送信息, ⽗进程接收信息IF_CHECK(pid = fork());if(pid == 0) { //⼦进程,先忽略退出处理防⽌成为僵⼫进程signal(SIGCHLD, SIG_IGN);while(fgets(msg.text, _INT_TEXT, stdin)){if(strcasecmp(msg.text, "quit\n") == 0){ //表⽰退出msg.type = '3';// 发送数据并检测IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen));break;}// 洗唛按发送普通信息msg.type = '2';IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen));}// 处理结算操作,并杀死⽗进程close(sd);kill(getppid(), SIGKILL);exit(0);}// 这⾥是⽗进程处理数据的读取for(;;){bzero(&msg, sizeof msg);IF_CHECK(recvfrom(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, &alen));[_INT_NAME-1] = msg.text[_INT_TEXT-1] = '\0';switch(msg.type){case'1':printf("%s 登录了聊天室!\n", );break;case'2':printf("%s 说了: %s\n", , msg.text);break;case'3':printf("%s 退出了聊天室!\n", );break;default://未识别的异常报⽂,程序直接退出fprintf(stderr, "msg is error! [%s:%d] => [%c:%s:%s]\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), msg.type, , msg.text);goto __exit;}}__exit:// 杀死并等待⼦进程退出close(sd);kill(pid, SIGKILL);waitpid(pid, NULL, -1);return0;}这⾥主要需要注意的是// 发送和接收的信息体struct umsg{char type; //协议 '1' => 向服务器发送名字, '2' => 向服务器发送信息, '3' => 向服务器发送退出信息char name[_INT_NAME]; //保存⽤户名字char text[_INT_TEXT]; //得到⽂本信息,空间换时间};传输和接收的数据格式, type表⽰协议或⾏为. 我这⾥细⼼了处理 name, text最后⼀个字符必须是 '\0'. 其它都是业务代码.再扯⼀点struct sockaddr_in addr = { AF_INET };等价于struct sockaddr_in addr;memset(&addr, 0, sizeof addr);addr.sin_family = AF_INET;也是⼀个C开发中技巧吧. 再扯⼀点linux上提供 bzero函数, 但是window上没有. 写了个通⽤的如下//7.0 置空操作#ifndef BZERO//v必须是个变量#define BZERO(v) \memset(&v,0,sizeof(v))#endif/* !BZERO */可以试试吧毕竟跨平台....好了那我们说 udp 聊天室的服务器设计思路. 就是服务器会维护⼀个客户端链表. 有信息来就⼴播. 好简单吧.就是这样.正常的事都简单.简单的是美的. 好了看代码总设计和实现. udpmulsrv.c#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <signal.h>#include <sys/wait.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>// 名字长度包含'\0'#define _INT_NAME (64)// 报⽂最⼤长度,包含'\0'#define _INT_TEXT (512)//4.0 控制台打印错误信息, fmt必须是双引号括起来的宏#define CERR(fmt, ...) \fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\__FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__)//4.1 控制台打印错误信息并退出, t同样fmt必须是 ""括起来的字符串常量#define CERR_EXIT(fmt,...) \CERR(fmt,##__VA_ARGS__),exit(EXIT_FAILURE)/** 简单的Linux上API错误判断检测宏, 好⽤值得使⽤*/#define IF_CHECK(code) \if((code) < 0) \CERR_EXIT(#code)// 发送和接收的信息体struct umsg{char type; //协议 '1' => 向服务器发送名字, '2' => 向服务器发送信息, '3' => 向服务器发送退出信息char name[_INT_NAME]; //保存⽤户名字char text[_INT_TEXT]; //得到⽂本信息,空间换时间};// 维护⼀个客户端链表信息,记录登录信息typedef struct ucnode {struct sockaddr_in addr;struct ucnode* next;} *ucnode_t ;// 新建⼀个结点对象static inline ucnode_t _new_ucnode(struct sockaddr_in* pa){ucnode_t node = calloc(sizeof(struct ucnode), 1);if(NULL == node)CERR_EXIT("calloc sizeof struct ucnode is error. ");node->addr = *pa;return node;}// 插⼊数据,这⾥head默认头结点是当前服务器结点static inline void _insert_ucnode(ucnode_t head, struct sockaddr_in* pa) {ucnode_t node = _new_ucnode(pa);node->next = head->next;head->next = node;}// 这⾥是有⽤户登录处理static void _login_ucnode(ucnode_t head, int sd, struct sockaddr_in* pa, struct umsg* msg) {_insert_ucnode(head, pa);head = head->next;// 从此之后才为以前的链表while(head->next){head = head->next;IF_CHECK(sendto(sd, msg, sizeof(*msg), 0, (struct sockaddr*)&head->addr, sizeof(struct sockaddr_in)));}}// 信息⼴播static void _broadcast_ucnode(ucnode_t head, int sd, struct sockaddr_in* pa, struct umsg* msg) {int flag = 0; //1表⽰已经找到了while(head->next) {head = head->next;if((flag) || !(flag=memcmp(pa, &head->addr, sizeof(struct sockaddr_in))==0)){IF_CHECK(sendto(sd, msg, sizeof(*msg), 0, (struct sockaddr*)&head->addr, sizeof(struct sockaddr_in)));}}}// 有⼈退出群聊static void _quit_ucnode(ucnode_t head, int sd, struct sockaddr_in* pa, struct umsg* msg) {int flag = 0;//1表⽰已经找到while(head->next) {if((flag) || !(flag = memcmp(pa, &head->next->addr, sizeof(struct sockaddr_in))==0)){IF_CHECK(sendto(sd, msg, sizeof(*msg), 0, (struct sockaddr*)&head->next->addr, sizeof(struct sockaddr_in))); head = head->next;}else { //删除这个退出的⽤户ucnode_t tmp = head->next;head->next = tmp->next;free(tmp);}}}// 销毁维护的对象池,没有往复杂的考虑了简单处理退出了static void _destroy_ucnode(ucnode_t* phead) {ucnode_t head;if((!phead) || !(head=*phead)) return;while(head){ucnode_t tmp = head->next;free(head);head = tmp;}*phead = NULL;}/** udp聊天室的服务器, ⼦进程⼴播信息,⽗进程接受信息*/int main(int argc, char* argv[]) {int sd, rt;struct sockaddr_in addr = { AF_INET };socklen_t alen = sizeof addr;struct umsg msg;ucnode_t head;// 这⾥简单检测if(argc != 3) {fprintf(stderr, "uage : %s [ip] [port]\n", argv[0]);exit(-1);}// 下⾯对接数据if((rt = atoi(argv[2]))<1024 || rt > 65535)CERR("atoi port = %s is error!", argv[2]);// 接着判断ip数据IF_CHECK(inet_aton(argv[1], &addr.sin_addr));addr.sin_port = htons(rt); //端⼝要采⽤⽹络字节序// 创建socketIF_CHECK(sd = socket(PF_INET, SOCK_DGRAM, 0));// 这⾥bind绑定设置的地址IF_CHECK(bind(sd, (struct sockaddr*)&addr, alen));//开始监听了head = _new_ucnode(&addr);for(;;){bzero(&msg, sizeof msg);IF_CHECK(recvfrom(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, &alen));[_INT_NAME-1] = msg.text[_INT_TEXT-1] = '\0';fprintf(stdout, "msg is [%s:%d] => [%c:%s:%s]\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), msg.type, , msg.text);// 开始判断处理switch(msg.type) {case'1':_login_ucnode(head, sd, &addr, &msg);break;case'2':_broadcast_ucnode(head, sd, &addr, &msg);break;case'3':_quit_ucnode(head, sd, &addr, &msg);break;default://未识别的异常报⽂,程序把其踢⾛fprintf(stderr, "msg is error! [%s:%d] => [%c:%s:%s]\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port), msg.type, , msg.text);_quit_ucnode(head, sd, &addr, &msg);break;}}// 这段代码是不会执⾏到这的, 可以加⼀些控制让其⾛到这. 看⼈close(sd);_destroy_ucnode(&head);return0;}这⾥主要围绕的结构就是// 维护⼀个客户端链表信息,记录登录信息typedef struct ucnode {struct sockaddr_in addr;struct ucnode* next;} *ucnode_t ;注册添加登录⼴播退出等.这⾥再扯⼀下. 关于C static开发技巧. C中有⼀种 *.h 开发模式, 全部采⽤static 内嵌代码段. 这样可以省略*.c ⽂件. ⼩巧的封装可以使⽤. 继续扯⼀点. 开发也写C++,虽然鄙视. C++ 中有个 *.hpp⽂件. ⽐较好. 它表达的意思是这个代码是开源的. 全部采⽤充⾎模型. 类中代码都放在类中实现.⾮常值得提倡. 这也是学boost的时候学到的. 很实在.好了说代码吧. 也⽐较随⼤流. 看看也都明⽩了. 简单分析⼀处吧// 这⾥是有⽤户登录处理static void _login_ucnode(ucnode_t head, int sd, struct sockaddr_in* pa, struct umsg* msg) {_insert_ucnode(head, pa);head = head->next;// 从此之后才为以前的链表while(head->next){head = head->next;IF_CHECK(sendto(sd, msg, sizeof(*msg), 0, (struct sockaddr*)&head->addr, sizeof(struct sockaddr_in)));}}因为我采⽤的头查法. 那就除了刚插⼊的头的下⼀个结点都需要发送登录信息. ⽐较精巧.好看编译命令gcc -g -Wall -o udpmulsrv.out udpmulsrv.cgcc -g -Wall -o udpmulclt.out udpmulclt.c最后测试截图如下很好玩,欢迎尝试.到这⾥基本上udp基础api 应该都了解了.从上⾯代码也许能看出来. 设计⽐较重要. 设计决定⼤思路.下次有机会要么分享开源的⽹络库,要么分享数据库开发.后记 错误是难免的,欢迎吐槽交流. ( ^_^ )/~~拜拜别董⼤(其⼀) ⾼适千⾥黄云⽩⽇曛,北风吹雁雪纷纷。
基于UDP的聊天程序
![基于UDP的聊天程序](https://img.taocdn.com/s3/m/6b198ee648649b6648d7c1c708a1284ac8500583.png)
基于UDP的聊天程序UDP是一种无连接的传输协议,而TCP是一种面向连接的传输协议。
UDP比TCP更适合实时应用,因为它不需要建立稳定的连接和保持状态。
以下是一个基于UDP的聊天程序的简单实现:1. 服务器端```import socket# 创建socket对象s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定端口s.bind(('127.0.0.1', 9999))# 等待客户端连接print('Server started...')while True:# 接收消息data, addr = s.recvfrom(1024)print('Received from %s:%s.' % addr)print(data.decode('utf-8'))# 发送消息reply = input('Input message to send: ')s.sendto(reply.encode('utf-8'), addr)```2. 客户端```import socket# 创建socket对象s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 输入服务器地址和端口号server_addr = input('Input server address: ')server_port = int(input('Input server port: '))# 发送消息while True:message = input('Input message to send: ')s.sendto(message.encode('utf-8'), (server_addr, server_port))# 接收消息data, addr = s.recvfrom(1024)print('Received from %s:%s.' % addr)print(data.decode('utf-8'))```运行程序后,客户端可以通过命令行输入消息并发送到服务器,服务器接收到消息后发送回复。
c#UDPTCP协议简单实现(简单聊天工具)
![c#UDPTCP协议简单实现(简单聊天工具)](https://img.taocdn.com/s3/m/080faa856aec0975f46527d3240c844769eaa00c.png)
c#UDPTCP协议简单实现(简单聊天⼯具)长时间没有摸这两个协议,写个代码温习下下⾯是界⾯【服务器界⾯】【登陆界⾯】【好友列表界⾯(我登陆了2个)】【聊天界⾯】下⾯⼤致讲解下⽤到的内容1、⽤户登陆于服务器通信⽤到的tcp协议,服务器接收到⽤户登陆信息(包括ip,端⼝,⽤户名等)后,返回已经登陆的⽤户列表信息(包括ip,端⼝,⽤户名等)给这个⽤户,同时服务器使⽤Udp协议向已经登陆的⽤户发送最新⽤户列表(包括ip,端⼝,⽤户名等)⽤于更新⽤户列表2、⽤户登陆成功后展⽰好友列表,并启动udp协议的监听(叫监听似乎不太合适,暂且这么叫吧形象),⽤以接收好友发来的消息和服务器返回的好友信息(1中提到的发送⽤户列表信息)3、关于聊天有被动接收到消息和主动发送消息先说主动发送消息吧:双击列表的某个好友打开聊天窗⼝,然后发送内容,通过udp协议向好友发送信息被动接收消息:当2中提到的udp监听器接收到消息,则打开聊天窗⼝,并显⽰信息4、⽤户退出时想服务器发送数据退出,⽤到的tcp协议,服务器接到到信息,更新在线⽤户列表并向其他⽤户发送⽤户最新列表进⾏更新(⽤到udp协议)⼝才不⾏,写的有点乱下⾯上代码解释下先来服务器代码,服务器我使⽤了控制台程序1using System;2using System.Collections.Generic;3using System.Text;4using .Sockets;5using System.Threading;6using ;7using System.IO;89namespace QQServer10 {11class Program12 {13public static List<string> userlist = new List<string>();14static TcpListener tl;15static NetworkStream ns;16static void Main(string[] args)17 {18//声明监听对象1920//声明⽹络流2122//IPEndPoint ip=new IPEndPoint(23 tl = new TcpListener(12345);24 tl.Start();25 Console.WriteLine("TcpListener Star");26//开启线程27 Thread th = new Thread(new ThreadStart(listen));28 th.IsBackground = true;29 th.Start();30while (true)31 {32string index = Console.ReadLine();33if (index == "exit")34break;3536 }3738 }39private static void listen()40 {41 Console.WriteLine("TcpListenering...");42while (true)43 {44//获得响应的Socket45 Socket sock = tl.AcceptSocket();46//通过该Socket实例化⽹络流47 ns = new NetworkStream(sock);48//ClientTcp是添加的类,下⾯会做说明49 ClientTcp ct = new ClientTcp(ns);50//ct_MyEvent⽅法注册ClientTcp类的MyEvent事件51 ct.MyEvent += new MyDelegate(ct_MyEvent);52//开启线程53 Thread th = new Thread(new ThreadStart(ct.TcpThread));54 th.IsBackground = true;55 th.Start();56 }57 }585960static void ct_MyEvent(string temp)61 {62if (temp.StartsWith("login:"))63 {64 temp = temp.Replace("login:", "");65 Console.WriteLine("UserLogin:" + temp);66string[] index = temp.Split(';');67if (!ContainsList(index[0]))68 {69 userlist.Add(temp);70 }71 SendUsersToUser(index[0]);72 }73else if (temp.StartsWith("out:"))74 {75 temp = temp.Replace("out:", "");76 Console.WriteLine("UserLoginOut:" + temp);77if (ContainsList(temp))78 {79 RemoveList(temp);80 }81 SendUsersToUser(temp);82 }83 }8485static void SendUsersToUser(string outuser)86 {87string message = GetUserStr();88 UdpClient uc;89foreach (string s in userlist)90 {91string[] _userstrindex=s.Split(';');92if (_userstrindex[0] == outuser)93continue;94string _ipsindex = _userstrindex[1];95string[] _ipindex = _ipsindex.Split(':');96byte[] b = System.Text.Encoding.UTF8.GetBytes("users" + message); 97//向本机的8888端⼝发送数据98 uc = new UdpClient();99 uc.Send(b, b.Length, _ipindex[0], int.Parse(_ipindex[1]));100 }101 }102103static string GetUserStr()104 {105 StringBuilder sb = new StringBuilder();106foreach (string s in userlist)107 {108if (sb.Length > 0)109 sb.Append("#");110 sb.Append(s);111 }112return sb.ToString();113 }114115static bool ContainsList(string str)116 {117foreach (string s in userlist)118 {119if (s.Split(';')[0] == str)120 {121return true;122 }123 }124return false;125 }126127static void RemoveList(string str)128 {129for (int i = userlist.Count - 1; i >= 0; i--)130 {131string s = userlist[i];132if (s.Split(';')[0] == str)133 {134 userlist.Remove(s);135 }136 }137 }138 }139140public delegate void MyDelegate(string temp);141class ClientTcp142 {143//设置⽹络流局部对象144private NetworkStream ns;145//声明类型为MyDelegate的事件MyEvent146public event MyDelegate MyEvent;147//构造函数中接收参数以初始化148public ClientTcp(NetworkStream ns)149 {150this.ns = ns;151 }152//服务器端线程所调⽤的⽅法153public void TcpThread()154 {155//获得相关的封装流156 StreamReader sr = new StreamReader(ns);157string temp = sr.ReadLine();158//接收到客户端消息后触发事件将消息回传159if (!temp.StartsWith("getuser"))160 {161 MyEvent(temp);162 }163 StringBuilder sb = new StringBuilder();164foreach (string s in erlist)165 {166if (sb.Length > 0)167 sb.Append("#");168 sb.Append(s);169 }170 StreamWriter sw = new StreamWriter(ns);171//转换为⼤写后发送消息给客户端172 sw.WriteLine(sb.ToString());173 sw.Flush();174 sw.Close();175 sr.Close();176 }177 }178 }View Code需要注意的地⽅:tl = new TcpListener(12345);这个地⽅使⽤了固定端⼝12345,所有客户端跟服务器进⾏通信必须使⽤这个端⼝Thread th = new Thread(new ThreadStart(ct.TcpThread));th.IsBackground = true;th.Start();这个地⽅为什么使⽤⼀个线程呢当接收到⼀个信息后需要进⾏处理,如果同时有好多信息进来的话容易堵塞,所有⽤线程,并且接收到⼀个信息马上将信息放到 ClientTcp ct = new ClientTcp(ns);这⾥,然后慢慢进⾏处理吧服务器接收到的消息有多种,怎么区分呢有登陆的信息,有退出的信息,有获取列表的信息,我们可以在发送的消息内⽤⼀些字段进⾏标记,例如在头部加上“getuser”等等的=======================================================下⾯是客户端的登陆1using System;2using System.Collections.Generic;3using ponentModel;4using System.Data;5using System.Drawing;6using System.Text;7using System.Windows.Forms;8using .Sockets;9using System.IO;10using ;1112namespace QQClient13 {14public partial class Login : Form15 {16private TcpClient tc;17//声明⽹络流18private NetworkStream ns;19public Login()20 {21 InitializeComponent();22 }2324private void button1_Click(object sender, EventArgs e)25 {26string username = textBox1.Text;27string ipstr = textBox2.Text;28string poitstr = textBox3.Text;2930 IPHostEntry ipe = Dns.GetHostEntry(Dns.GetHostName());31 IPAddress ipa = null;32foreach (IPAddress ip in ipe.AddressList)33 {34if (ip.AddressFamily == .Sockets.AddressFamily.InterNetworkV6) 35continue;36 ipa = ip;37break;38 }3940 StringBuilder sb = new StringBuilder();41 sb.Append("login:");42 sb.Append(username + ";");43 sb.Append(ipa.ToString() + ":");44 Random r = new Random();45int port = r.Next(2000, 65535);46 sb.Append(port.ToString());4748try49 {50 tc = new TcpClient(ipstr, int.Parse(poitstr));51 }52catch53 {54 MessageBox.Show("⽆法连接到主机");55 }56//实例化⽹络流对象57 ns = tc.GetStream();58 StreamWriter sw = new StreamWriter(ns);59 StreamReader sr = new StreamReader(ns);60//将TextBox1的值传给服务器端61 sw.WriteLine(sb.ToString());62 sw.Flush();63//接收服务器端回传的字符串64string users = sr.ReadLine();6566 sr.Close();67 sw.Close();6869 Main main=new Main();70 ername=username;71 ers=users;72 main.Port = port;73 main.ThisIP = ipa.ToString();74 main.ServerIP = textBox2.Text;75 main.ServerPort = textBox3.Text;76this.Hide();77 main.ShowDialog();78 }7980private void button2_Click(object sender, EventArgs e)81 {82 Application.Exit();83 }84 }85 }View Code列表界⾯1using System;2using System.Collections.Generic;3using ponentModel;4using System.Data;5using System.Drawing;6using System.Text;7using System.Windows.Forms;8using .Sockets;9using System.IO;10using System.Threading;11using ;1213namespace QQClient14 {15public partial class Main : Form16 {17public string Username { get; set; }18public string Users { get; set; }19public int Port { get; set; }20public string ServerIP;21public string ServerPort;22public string ThisIP { get; set; }23public static List<Talking> TalkList = new List<Talking>();24public List<User> userList = new List<User>();25public Main()26 {27 InitializeComponent();28 }2930private void Main_Load(object sender, EventArgs e)31 {32//Control.CheckForIllegalCrossThreadCalls = false;33this.Text = Username;34 LoadUser();35 StartListen();36 }3738private void LoadUser()39 {40if (string.IsNullOrEmpty(Users))41return;42this.listView1.Items.Clear();43 userList.Clear();44string[] _userindex = Users.Split('#');45foreach (string s in _userindex)46 {47string[] _index = s.Split(';');48string _username = _index[0];49//string[] _ipinex = _index[1].Split(':');50//string ip = _ipinex[0];51//string port = _ipinex[1];52if (_username != Username)53 {54//TreeNode tn = new TreeNode();55//tn.Text = _username;56//tn.Tag = _index[1];57//this.treeView1.Nodes.Add(tn);5859 ListViewItem lvitem = new ListViewItem();6061 lvitem.ImageIndex = 0;62 lvitem.Text = _username;63 lvitem.Tag = _index[1];64this.listView1.Items.Add(lvitem);65 userList.Add(new User() { UserName = _username, Ips = _index[1] });66 }67 }697071private void button2_Click(object sender, EventArgs e)72 {73 Application.Exit();74 }7576private void button1_Click(object sender, EventArgs e)77 {78try79 {80 TcpClient tc = new TcpClient(ServerIP, int.Parse(ServerPort));81//实例化⽹络流对象82 NetworkStream ns = tc.GetStream();83 StreamWriter sw = new StreamWriter(ns);84 StreamReader sr = new StreamReader(ns);85//将TextBox1的值传给服务器端86 sw.WriteLine("getuser");87 sw.Flush();88//接收服务器端回传的字符串89 Users = sr.ReadLine();90 sr.Close();91 sw.Close();92 LoadUser();93 }94catch95 { }96 }9798private void Main_FormClosed(object sender, FormClosedEventArgs e)99 {100try101 {102 TcpClient tc = new TcpClient(ServerIP, int.Parse(ServerPort));103//实例化⽹络流对象104 NetworkStream ns = tc.GetStream();105 StreamWriter sw = new StreamWriter(ns);106//将TextBox1的值传给服务器端107 sw.WriteLine("out:" + Username);108 sw.Flush();109 sw.Close();110 iswork = false;111 }112catch113 { }114 Application.Exit();115 }116117private void listView1_MouseDoubleClick(object sender, MouseEventArgs e) 118 {119if (this.listView1.SelectedItems.Count > 0)120 {121 ListViewItem lvitem = this.listView1.SelectedItems[0];122string toname = lvitem.Text;123string toips = lvitem.Tag.ToString();124 Talking t = isHaveTalk(toname);125if (t != null)126 {127 t.Focus();128 }129else130 {131 Talking talk = new Talking();132 erName = Username;133 talk.ToName = toname;134 talk.ToIP = toips;135 TalkList.Add(talk);136 talk.Show();137 }138 }139 }140141private Talking isHaveTalk(string toname)142 {143foreach (Talking tk in TalkList)144 {145if (tk.ToName == toname)146return tk;147 }148return null;149 }150151public static void RemoveTalking(Talking _talk)153foreach (Talking tk in TalkList)154 {155if (tk.ToName == _talk.ToName)156 {157 TalkList.Remove(_talk);158return;159 }160 }161 }162163bool iswork = false;164 UdpClient uc = null;165private void StartListen()166 {167168 iswork = true;169 Thread th = new Thread(new ThreadStart(listen));170//设置为后台171 th.IsBackground = true;172 th.Start();173 }174private void listen()175 {176 uc = new UdpClient(Port);177 IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);178while (iswork)179 {180//获得Form1发送过来的数据包181string text = System.Text.Encoding.UTF8.GetString(uc.Receive(ref iep)); 182if (text.StartsWith("message"))183 {184 text = text.Substring(7);185int indexof = text.IndexOf("#");186string fromuser = text.Substring(0, indexof);187string message = text.Substring(indexof + 1);188 Talking _tk = isHaveTalk(fromuser);189if (_tk != null)190 {191this.BeginInvoke(new MethodInvoker(delegate()192 {193 _tk.Focus();194 _tk.AddMessage(message, true);195 }));196 }197else198 {199//Talking talk = new Talking(message);200//erName = Username;201//talk.ToName = fromuser;202//talk.ToIP = GetIP(fromuser);203//TalkList.Add(talk);204//talk.Show();205this.BeginInvoke(new MethodInvoker(delegate()206 {207this.CreatTalking(text);208 }));209//Thread th = new Thread(new ParameterizedThreadStart(CreatTalking)); 210//th.IsBackground = true;211//th.Start(text);212 }213//加⼊ListBox214//this.listBox1.Items.Add(text);215 }216else if (text.StartsWith("users"))217 {218 text = text.Substring(5);219 Users = text;220 LoadUser();221 }222 }223 }224225public void CreatTalking(object _text)226 {227string text = _text.ToString();228int indexof = text.IndexOf("#");229string fromuser = text.Substring(0, indexof);230string message = text.Substring(indexof + 1);231 Talking talk = new Talking(message);232 erName = Username;233 talk.ToName = fromuser;234 talk.ToIP = GetIP(fromuser);235 TalkList.Add(talk);236 talk.Show();237 }238239private string GetIP(string toname)240 {241foreach (User user in userList)242 {243if (erName == toname)244return user.Ips;245 }246return"";247 }248 }249public class User250 {251private string userName;252253public string UserName254 {255get { return userName; }256set { userName = value; }257 }258private string ips;259260public string Ips261 {262get { return ips; }263set { ips = value; }264 }265 }266 }View Code聊天界⾯1using System;2using System.Collections.Generic;3using ponentModel;4using System.Data;5using System.Drawing;6using System.Text;7using System.Windows.Forms;8using .Sockets;9using System.Threading;1011namespace QQClient12 {13public partial class Talking : Form14 {15public string UserName { get; set; }16public string ToName { get; set; }17public string ToIP { get; set; }1819 UdpClient uc;20public Talking()21 {22 InitializeComponent();23 }2425string getmessage = string.Empty;26public Talking(string message)27 {28 getmessage = message;29 InitializeComponent();30 }3132private void Talking_Load(object sender, EventArgs e)33 {34 uc = new UdpClient();35this.Text = "和" + ToName + "聊天中";36if (!string.IsNullOrEmpty(getmessage))37 {38 ShowTalking();39 AddMessage(getmessage, true);40 }41 }4243private void button1_Click(object sender, EventArgs e) 44 {45string temp = this.textBox1.Text; //保存TextBox⽂本 46//将该⽂本转化为字节数组47byte[] b = System.Text.Encoding.UTF8.GetBytes("message" + UserName + "#" + temp);48//向本机的8888端⼝发送数据49string[] _ip = ToIP.Split(':');50 uc.Send(b, b.Length, _ip[0], int.Parse(_ip[1]));51 AddMessage(temp, false);52this.textBox1.Clear();53 }54public void AddMessage(string str, bool isuser)55 {56int startindex = this.richTextBox1.Text.Length;5758string message = string.Empty;5960if (isuser)61 message = "【" + ToName + "】 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + str + "\n"; 62else63 message = "【" + UserName + "】 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + str + "\n"; 64this.richTextBox1.AppendText(message);65this.richTextBox1.Select(startindex, message.Length);66if (isuser)67 {68this.richTextBox1.SelectionAlignment = HorizontalAlignment.Left;69 }70else71 {72this.richTextBox1.SelectionAlignment = HorizontalAlignment.Right;73 }74this.richTextBox1.Select(this.richTextBox1.Text.Length, 0);75 }7677 [System.Runtime.InteropServices.DllImport("user32")]78private static extern long FlashWindow(IntPtr hwnd, bool bInvert);7980private static void FlashWindow(object _handle)81 {82 IntPtr handle = (IntPtr)_handle;83int flashindex = 0;84while (true)85 {86if (flashindex > 5)87break;88 FlashWindow(handle, true);89 flashindex++;90 Thread.Sleep(500);91 }92 }9394public void ShowTalking()95 {96 Thread _thread = new Thread(FlashWindow);97 _thread.IsBackground = true;98 _thread.Start(this.Handle);99 }100101private void Talking_FormClosed(object sender, FormClosedEventArgs e)102 {103 Main.RemoveTalking(this);104 }105106private void button2_Click(object sender, EventArgs e)107 {108this.Close();109 }110 }111 }View Code⼤致总结下:tcp必须建⽴连接才可以进⾏通信udp不需要建⽴通信但是两者都需要⼀个监听来接收消息。
一个TCP和UPD聊天、传收文件程序
![一个TCP和UPD聊天、传收文件程序](https://img.taocdn.com/s3/m/461ca318f18583d049645931.png)
本文通过例子,介绍了如何在局域网中进行聊天、互发文件以及抓取对方屏幕保存为文件。
程序还包括了取得本机和对方的IP、计算机名称。
滚动ListBox控件等功能。
一、启动终止监听线程(只介绍TCP)由于此程序可以即时切换状态,因此需要结束仍处于接受状态的线程。
//TCP监听线程UINT _ListenTcpThread(LPVOID lparam){CMyQQDlg *pDlg=(CMyQQDlg *)lparam;CSocket sockSrvr;pDlg->m_Potr=PORT+pDlg->m_server;//保存当前使用端口,用于关闭int createSucceed=sockSrvr.Create(pDlg->m_Potr);int listenSucceed=sockSrvr.Listen();//开始监听CSocket recSo;SOCKADDR_IN client;int iAddrSize=sizeof(client);int acceptSucceed=sockSrvr.Accept(recSo,(SOCKADDR *)&client,&iAddrSize); //接受连接并取得对方IPsockSrvr.Close();char flag[FLAG]={0}; //接受标示,用于判断接受到的是信息,文件等if(recSo.Receive(flag,FLAG)!=2){return -1;}pDlg->m_type=flag[0];if(pDlg->m_type==''D'') return 0;//终止此线程pThreadLisen=::AfxBeginThread(_ListenTcpThread,pDlg);pDlg->ReceiveFileMsg(recSo,client);return 0;}关闭if(m_nSockType==SOCK_TCP){DWORD dwStatus;if (pThreadLisen != NULL){if(::GetExitCodeThread(pThreadLisen->m_hThread, &dwStatus)==0){int errror=GetLastError();return;if (dwStatus == STILL_ACTIVE){CSocket sockClient;sockClient.Create();CString ip,strError;ip="127.0.0.1";int conn=sockClient.Connect(ip, m_Potr);if(conn==0){AfxMessageBox("关闭错误!"+GetError(GetLastError()));sockClient.ShutDown(2);sockClient.Close();return;}sockClient.Send("D",FLAG); //结束}}二.发送、接受文件。
c语言udp通讯例程
![c语言udp通讯例程](https://img.taocdn.com/s3/m/8984338c2dc58bd63186bceb19e8b8f67d1cef67.png)
c语言udp通讯例程以下是一个简单的 C 语言 UDP 通讯例程,包括一个发送端和一个接收端:**发送端代码(sender.c):**```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>void sendMessage(int sock, const char *message) {size_t messageLength = strlen(message);// 发送数据send(sock, message, messageLength, 0);}int main() {int sock;struct sockaddr_in serverAddress;char message[1024];// 创建 UDP 套接字if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 设置服务器地址serverAddress.sin_family = AF_INET;serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); // 请将这里的地址替换为接收端的实际 IP 地址serverAddress.sin_port = htons(54321); // 请将这里的端口替换为接收端的实际端口printf("Enter a message: ");scanf("%s", message);// 发送消息sendMessage(sock, message);// 关闭套接字close(sock);return 0;}```**接收端代码(receiver.c):**```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>void receiveMessage(int sock) {char message[1024];size_t messageLength;// 接收数据messageLength = recv(sock, message, sizeof(message) - 1, 0);message[messageLength] = '\0';printf("Received message: %s\n", message);}int main() {int sock;struct sockaddr_in serverAddress;socklen_t serverAddressLength = sizeof(serverAddress);// 创建 UDP 套接字if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 绑定套接字到本地地址serverAddress.sin_family = AF_INET;serverAddress.sin_addr.s_addr = INADDR_ANY;serverAddress.sin_port = htons(54321); // 请确保这里的端口与发送端使用的端口相同if (bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1) {perror("Failed to bind socket");exit(EXIT_FAILURE);}// 接收消息receiveMessage(sock);// 关闭套接字close(sock);return 0;}```这个例子中,发送端发送一个 UDP 数据包到接收端,接收端接收到数据包并打印出消息内容。
VC实现最简单的UDP通信
![VC实现最简单的UDP通信](https://img.taocdn.com/s3/m/0b4938325a8102d276a22f35.png)
VC实现最简单的UDP通信//Client端代码#include <winsock2.h>#include <iostream.h>#include <stdio.h>void initClient();int main(){initClient();return 0;}void initClient(){WSADATA wsaData;int error=WSAStartup(MAKEWORD(2,2),&wsaData);if(error!=0){cout<<"初始化DLL失败"<<endl;return;}if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2){WSACleanup();cout<<"版本出错"<<endl;return;}SOCKET s=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN sockSend;sockSend.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");sockSend.sin_port=htons(4000);sockSend.sin_family=AF_INET;char buff[1024];strcpy(buff,"hello,it's the first!");int i=500;while(--i){int lenword;lenword=sendto(s,buff,strlen(buff)+1,0,(sockaddr*)&sockSend,sizeof(sockaddr));cout<<lenword<<","<<sockSend.sin_port<<":"<<sockSend.sin_addr.S_un.S _addr<<endl;}closesocket(s);WSACleanup();}//Server端代码#include <winsock2.h>#include <iostream>#include <stdio.h>using namespace std;void initNet();int main(){initNet();return 0;}void initNet(){WSADATA wsaData;int error=WSAStartup(MAKEWORD(1,1),&wsaData);if(error!=0){cout<<"初始化DLL失败"<<endl;return;}if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1) {WSACleanup();cout<<"版本出错"<<endl;return;}SOCKET s=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN sockSrc;sockSrc.sin_addr.S_un.S_addr=htonl(INADDR_ANY);sockSrc.sin_port=htons(4000);sockSrc.sin_family=AF_INET;bind(s,(SOCKADDR *)&sockSrc,sizeof(SOCKADDR));char recBuff[1024];memset(recBuff,0,1024);SOCKADDR_IN sockRec;int len=sizeof(SOCKADDR);int x=-1;cout<<sockSrc.sin_port<<":"<<sockSrc.sin_addr.S_un.S_addr<<endl; while(x==-1){x=recvfrom(s,recBuff,sizeof(recBuff),0,(sockaddr *)&sockRec,&len);}printf("the receive is:%s,%d \n",recBuff,x);closesocket(s);WSACleanup();}程序能够运行,客户端发送的数据服务端收不道,运行时客户端和服务都再一台机器Windows 95环境下,基于TCP/IP协议,用Winsock完成了话音的一端传输摘要:在Windows 95环境下,基于TCP/IP协议,用Winsock完成了话音的端到端传输。
基于UDP的网络聊天程序
![基于UDP的网络聊天程序](https://img.taocdn.com/s3/m/68ed68e9998fcc22bcd10dd7.png)
创建一个MFC的对话框工程Chat,界面如图下面是实现步骤:一、调用Afxstock全局函数初始化套接字库,在CChatApp::InitInstance()中添加代码:if (!AfxSocketInit()){AfxMessageBox("加载字库失败!");return FALSE;}二、在CChatDlg类中添加一个成员函数:stocketInit(),并在CChatDlg::OnInitDialog()中调用一下,代码如下:BOOL CChatDlg::stocketInit(){m_socket=socket(AF_INET,SOCK_DGRAM,0);if (INVALID_SOCKET==m_socket){MessageBox("创建套接字失败!");return FALSE;}SOCKADDR_IN socket_in;socket_in.sin_family=AF_INET;socket_in.sin_port=htons(3000);socket_in.sin_addr.S_un.S_addr=htonl(INADDR_ANY);int retval;retval=bind(m_socket,(SOCKADDR*)&socket_in,sizeof(SOCKADDR));if (SOCKET_ERROR==retval){closesocket(m_socket);MessageBox("绑定套接字失败!");return FALSE;}return TRUE;}三、在CChatDlg::OnInitDialog()中创建一个线程,用于接收数据。
这是本程序的关键一步,1、接收数据的recvfrom函数会一直等待数据的到来,如果放在主线程中会赌塞系统,所以必须在建一个线程实现。
2、线程必须接收对话框传来的套接字,用来接收数据,而得到的数据必须回传给对话框显示出来,但是线程只能接收一个LPVOID型的参数,要同时接受2个参数,就需要提前定义一个struct,里面包含2个成员:sock和hwnd,把这个结构的指针做为参数传递给线程。
C#局域网聊天工具、消息推送实现思路与源码
![C#局域网聊天工具、消息推送实现思路与源码](https://img.taocdn.com/s3/m/81542d24ed630b1c59eeb5cd.png)
C#局域网聊天工具怎么实现?1.网络通讯编程的基础便是协议,信息的发送常用的协议有面向连接的TCP协议,以及不面向连接的UDP协议2.TCP:TransmissionControlProtocol传输控制协议,其是一种面向连接的、可靠的字节流服务。
面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。
这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。
3.UDP:UserDatagramProtocol用户数据报协议(RFC768),UDP传送数据前并不与对方建立连接,即UDP是无连接的,在传输数据前,发送方和接收方相互交换信息使双方同步。
4.系统也要定义自己的通讯协议,来完成一些系统的功能,如用户上,下线的通知,都要定义自己的通讯协议来完成相应的功能!也可以称这种自定义的协议为“命令”.5.下面以著名的飞鸽传书为例,说明其自定义的协议(命令)IPMSG_NOOPERATION不进行任何操作IPMSG_BR_ENTRY用户上线IPMSG_BR_EXIT用户退出IPMSG_ANSENTRY通报在线IPMSG_SENDMSG发送消息IPMSG_RECVMSG通报收到消息IPMSG_GETFILEDATA请求通过TCP传输文件IPMSG_RELEASEFILES停止接收文件IPMSG_GETDIRFILES请求传输文件夹以“IPMSG_BR_ENTRY用户上线”和“IPMSG_ANSENTRY通报在线”为例说明命令处理流程:当程序启动时,命令IPMSG_BR_ENTRY被广播到网络中,向所有在线的用户提示一个新用户的到达(即表示“我来了”);所有在线用户将把该新上线用户添加到自己的用户列表中,并向该新上线用户发送IPMSG_ANSENTRY命令(即表示“我在线”);该新上线用户接收到IPMSG_ANSENTRY命令后即将在线用户添加到自己的用户列表中。
udp聊天程序C#开发UDP协议聊天程序
![udp聊天程序C#开发UDP协议聊天程序](https://img.taocdn.com/s3/m/f90b5a3367ec102de2bd8958.png)
listener.Close; } } 服务器端窗体加载时StartListenter思路方法开启监听实现代码如下:
private void frmServer_Load(object sender, EventArgs e) { this.Hide;//隐藏服务器端窗体 StartListener; //监听思路方法 } 客户端实现具体步骤如下:
服务器端实现具体步骤如下:
(1)在VS2005工程中添加个窗体
(2)首先在代码设计器窗口中引入using .Net.Sockets和using .Net命名空间 (3)主要代码如下
通过UdpClient类例子化个新对象listener用于监听信息同时例子化IPEndPo类个新对象groupEP(指定任意 IP地址和指定端口号)将其作为listener对象Receive思路方法参数以达到广播作用 bool done = false; private const listenPort = 11000; //设置端口 private void StartListener { UdpClient listener = UdpClient(listenPort); 使用UDP协议 IPEndPo groupEP = IPEndPo(IPAddress.Any, listenPort); //任意IP try { while (!done)//使用永真循环另其直处于监听状态 { s = listener.Receive(ref groupEP); strIP; strIP ="信息来自"+ groupEP.Address.;//获得发信人IP strInfo=Encoding.GetEncoding("gb2312").GetString(s, 0, s.Length);//获得信息 MessageBox.Show(strInfo, strIP); } } catch (Exception e) { Console.WriteLine(e.); } finally {
C#中使用UDP通信的示例
![C#中使用UDP通信的示例](https://img.taocdn.com/s3/m/efc5c5fe112de2bd960590c69ec3d5bbfc0ada52.png)
C#中使⽤UDP通信的⽰例⽹络通信协议中的UDP通信是⽆连接通信,客户端在发送数据前⽆需与服务器端建⽴连接,即使服务器端不在线也可以发送,但是不能保证服务器端可以收到数据。
本⽂实例即为基于C#实现的UDP通信。
具体功能代码如下:服务器端代码如下static void Main(string[] args){UdpClient client = null;string receiveString = null;byte[] receiveData = null;//实例化⼀个远程端点,IP和端⼝可以随意指定,等调⽤client.Receive(ref remotePoint)时会将该端点改成真正发送端端点IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);while (true){client = new UdpClient(11000);receiveData = client.Receive(ref remotePoint);//接收数据receiveString = Encoding.Default.GetString(receiveData);Console.WriteLine(receiveString);client.Close();//关闭连接}}客户端代码如下:static void Main(string[] args){string sendString = null;//要发送的字符串byte[] sendData = null;//要发送的字节数组UdpClient client = null;IPAddress remoteIP = IPAddress.Parse("127.0.0.1");int remotePort = 11000;IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);//实例化⼀个远程端点while (true){sendString = Console.ReadLine();sendData = Encoding.Default.GetBytes(sendString);client = new UdpClient();client.Send(sendData, sendData.Length, remotePoint);//将数据发送到远程端点client.Close();//关闭连接}以上就是C#中使⽤UDP通信的⽰例的详细内容,更多关于c# udp通信的资料请关注其它相关⽂章!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#include <signal.h>#define CLIENT_LOGIN 100#define CLIENT_CHAT 200#define CLIENT_QUIT 300#define SERVER_CHA T 400#define SERVER_QUIT 500struct node{char name[20];struct sockaddr_in client_addr;struct node *next;};struct message{long type;char name[20];char mtext[512];};struct node *create_list(void);void insert_list(struct node *, char *, struct sockaddr_in *);void delete_list(struct node *, char *);void recv_message(int , struct node *);void send_message(int , struct sockaddr_in *, pid_t );void client_login(int , struct node *, struct message *, struct sockaddr_in *); void client_chat(int , struct node *, struct message *);void client_quit(int , struct node *, struct message *);void server_chat(int , struct node *, struct message *);void server_quit(int , struct node *, struct message *);void brocast_msg(int , struct node *, struct message *);void father_func(int sig_no){return ;}int main(int argc, const char *argv[]){int socket_fd;pid_t pid;struct sockaddr_in server_addr;struct node *head;if (argc < 3){fprintf(stderr, "usages : %s ip port\n", argv[0]);exit(-1);}if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("failed to create socket");exit(-1);}head = create_list();server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[2]));server_addr.sin_addr.s_addr = inet_addr(argv[1]);if (bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("failed to bind");exit(-1);}if ((pid = fork()) < 0) //创建子经常{perror("failed to fork pid");exit(-1);}if (pid == 0)recv_message(socket_fd, head);elsesend_message(socket_fd, &server_addr, pid);return 0;}struct node *create_list(void){struct node *head;head = (struct node *)malloc(sizeof(struct node));head->next = NULL;return head;}void insert_list(struct node *head, char *name, struct sockaddr_in *client_addr) {struct node *new;new = (struct node *)malloc(sizeof(struct node));strcpy(new->name, name);new->client_addr = *client_addr;new->next = head->next;head->next = new;return ;}void delete_list(struct node *head, char *name){struct node *p = head->next;struct node *q = head;while (p != NULL){if (strcmp(p->name, name) == 0)break;p = p->next;q = q->next;}q->next = p->next;p->next = NULL;free(p);return ;}void recv_message(int socket_fd, struct node *head){struct message msg;struct sockaddr_in client_addr;int client_addrlen = sizeof(struct sockaddr);while (1){if (recvfrom(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)&client_addr, &client_addrlen) < 0){perror("failed to recvform client");exit(-1);}switch(msg.type){case CLIENT_LOGIN:client_login(socket_fd, head, &msg, &client_addr);break;case CLIENT_CHA T:client_chat(socket_fd, head, &msg);break;case CLIENT_QUIT:client_quit(socket_fd, head, &msg);break;case SERVER_CHA T:server_chat(socket_fd, head, &msg);break;case SERVER_QUIT:server_quit(socket_fd, head, &msg);break;default:break;}}return ;}void send_message(int socket_fd, struct sockaddr_in *server_addr, pid_t pid){struct message msg;char buf[512];signal(getppid(), father_func);while (1){usleep(500);printf(">");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;strcpy(msg.mtext, buf);strcpy( , "server");msg.type = SERVER_CHA T;if (strncmp(buf, "quit", 4) == 0){msg.type = SERVER_QUIT;if (sendto(socket_fd, &msg, sizeof(msg), 0,(struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) {perror("failed to send server_quit message");exit(-1);}pause();kill(pid, SIGKILL);waitpid(pid, NULL, 0);exit(0);}if (sendto(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0){perror("failed to send server_chat message");exit(-1);}}return ;}void client_login(int socket_fd, struct node *head, struct message *msg, struct sockaddr_in *client_addr){printf("********Login In********\n");printf("%s is Login In\n", msg->name);printf("************************\n");insert_list(head, msg->name, client_addr);brocast_msg(socket_fd, head, msg);return ;}void client_chat(int socket_fd, struct node *head, struct message *msg){printf("********Group Chat********\n");printf("name: %s\n", msg->name);printf("msg: %s\n", msg->mtext);printf("**************************\n");brocast_msg(socket_fd, head, msg);return ;}void client_quit(int socket_fd, struct node *head, struct message *msg){printf("*********Quit Msg********\n");printf("%s is Quit\n", msg->name);printf("*************************\n");delete_list(head, msg->name);brocast_msg(socket_fd, head, msg);return ;}void server_chat(int socket_fd, struct node *head, struct message *msg){printf("********Server Msg*********\n");printf("msg: %s\n", msg->mtext);printf("***************************\n");brocast_msg(socket_fd, head, msg);return ;}void server_quit(int socket_fd, struct node *head, struct message *msg){brocast_msg(socket_fd, head, msg);kill(getppid(), SIGUSR1);return ;}void brocast_msg(int socket_fd, struct node *head, struct message *msg){struct node *p = head->next;while(p != NULL){if (msg->type == CLIENT_LOGIN){if (strcmp(p->name, msg->name) == 0){p = p->next;continue;}}sendto(socket_fd, msg, sizeof(struct message), 0, (struct sockaddr *)&(p->client_addr), sizeof(struct sockaddr));p = p->next;}return ; }#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#include <signal.h>#define CLIENT_LOGIN 100#define CLIENT_CHAT 200#define CLIENT_QUIT 300#define SERVER_CHA T 400#define SERVER_QUIT 500struct message{long type;char name[20];char mtext[512];};void recv_message(int );void send_message(int , struct sockaddr_in *, char *, pid_t);void login_msg(struct message *);void group_msg(struct message *);void quit_msg(struct message *);void server_msg(struct message *);void server_quit(void);int main(int argc, char *argv[]){pid_t pid;int server_fd;struct sockaddr_in server_addr;if (argc < 4){fprintf(stderr, "usages: %s ip port name\n", argv[0]);exit(-1);}if ((server_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("failed to create server_fd");exit(-1);}server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[2]));server_addr.sin_addr.s_addr = inet_addr(argv[1]);if ((pid = fork()) < 0){perror("failed to fork pid");exit(-1);}if (pid == 0)recv_message(server_fd);elsesend_message(server_fd, &server_addr, argv[3], pid);return 0;}void recv_message(int server_fd){struct message msg;while (1){memset(&msg, 0, sizeof(msg));if (recvfrom(server_fd, &msg, sizeof(msg), 0, NULL, NULL) < 0){perror("failed to recv server message");exit(-1);}switch(msg.type){case CLIENT_LOGIN:login_msg(&msg);break;case CLIENT_CHA T:group_msg(&msg);break;case CLIENT_QUIT:quit_msg(&msg);break;case SERVER_CHA T:server_msg(&msg);break;case SERVER_QUIT:server_quit();break;default:break;}}return ;}void send_message(int server_fd, struct sockaddr_in *server_addr, char *name, pid_t pid) {struct message msg;char buf[512];msg.type = CLIENT_LOGIN;strcpy(, name);if (sendto(server_fd, &msg, sizeof(msg), 0,(struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) {perror("failed to send login message");exit(-1);}while(1){memset(buf, 0, sizeof(buf));memset(&msg, 0, sizeof(msg));usleep(500);printf(">");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;strcpy(msg.mtext, buf);strcpy(, name);msg.type = CLIENT_CHAT;if (strncmp(buf, "quit", 4) == 0){msg.type = CLIENT_QUIT;if (sendto(server_fd, &msg, sizeof(msg), 0,(struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) {perror("failed to send quit message");exit(-1);}kill(pid, SIGKILL);waitpid(pid, NULL, 0);exit(0);}if (sendto(server_fd, &msg, sizeof(msg), 0,(struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) {perror("failed to send group message");exit(-1);}}return ;}void login_msg(struct message *msg)printf("######## Login in ########\n");printf("%s is login in\n", msg->name);printf("######## Login in ########\n");return ;}void group_msg(struct message *msg){printf("******** Group Msg ********\n");printf("name: %s\n", msg->name);printf("msg: %s\n", msg->mtext);printf("******** Group Msg ********\n");return ;}void quit_msg(struct message *msg){printf("######## Quit Msg ########\n");printf("%s is Quit\n", msg->name);printf("######## Quit Msg ########\n");return ;}void server_msg(struct message *msg){printf("******** Server Msg ********\n");printf("msg: %s\n", msg->mtext);printf("******** Server Msg ********\n");return ;}void server_quit(void ){kill(getppid(), SIGKILL);exit(0);}。