基于socket实现的简单的聊天程序
记得八年前第一次使用socket做的一个五子棋程序,需要序列化棋子对象,传递到对方的电脑上。 一个偶然的机会,第二次使用socket做点事情。先看聊天服务器端的实现:
服务器端要实现以下功能:
1、启动服务,开启监听
2、持续不断地接收消息
3、发送消息
启动服务,创建监听socket,绑定Ip和端口:
/// <summary>
/// 启动服务
/// </summary>
private void Start()
{
socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress address = IPAddress.Parse("10.0.0.31"); IPEndPoint point = new IPEndPoint(address, ); socketwatch.Bind(point); //将套接字的监听队列长度限制为20
socketwatch.Listen(); //创建一个监听线程
threadwatch = new Thread(watchconnecting); threadwatch.IsBackground = true; threadwatch.Start();
}
创建接收数据的Socket:
//监听客户端发来的请求
private void watchconnecting()
{
Socket connection = null;
while (true) //持续不断监听客户端发来的请求
{
try
{
connection = socketwatch.Accept();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); //提示套接字监听异常
break;
}
//获取客户端的IP和端口号
IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port; //让客户显示"连接成功的"的信息
string sendmsg = "连接服务端成功!\r\n" + "本地IP:" + clientIP + ",本地端口" + clientPort.ToString();
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
connection.Send(arrSendMsg); RemoteEndPoint = connection.RemoteEndPoint.ToString(); //客户端网络结点号
dic.Add(RemoteEndPoint, connection); //添加客户端信息 IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint; //创建一个通信线程
ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
Thread thread = new Thread(pts);
thread.IsBackground = true;//设置为后台线程,随着主线程退出而退出
//启动线程
thread.Start(connection);
}
}
socketwatch.Accept() 会创建一个新的socket,它用来负责和某个客户端的通讯。 接收数据:
private void recv(object socketclientpara)
{ Socket socketServer = socketclientpara as Socket;
while (true)
{
byte[] arrServerRecMsg = new byte[ * ];
try
{
int length = socketServer.Receive(arrServerRecMsg); string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, , length); this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strSRecMsg, IdentityName = socketServer.RemoteEndPoint.ToString() });
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
socketServer.Close();
break;
}
}
}
把从客户端接收过来的字节流变为字符串,然后添加到页面上。
发送消息:
private static object lockPool = new object();
public static ObservableCollection<Message> MessagePool = new ObservableCollection<Message>();
private void send_Click(object sender, RoutedEventArgs e)
{
string msg = this.message.Text; this.message.Clear(); lock (lockPool)
{
MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = msg, IdentityName = "wbq" });
} string sendMsg = msg;
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg); if (dic.Count > )
dic.First().Value.Send(bytes);
}
dic.First().Value.Send,从字典中获取到之前创建好的通讯socket,然后调用send方法。 客户端需要实现以下功能:
1、和服务器建立连接
2、接收数据
3、发送数据 建立连接:
private void Start()
{ //定义一个套接字监听
socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var servers= GetServers(); if (servers.Count > )
{ //获取文本框中的IP地址
IPAddress address = IPAddress.Parse(servers.First().IPToPing); //将获取的IP地址和端口号绑定在网络节点上
IPEndPoint point = new IPEndPoint(address, int.Parse(servers.First().Port)); try
{
//客户端套接字连接到网络节点上,用的是Connect
socketclient.Connect(point);
}
catch (Exception)
{
//MessageBox.
MessageBox.Show("连接失败\r\n");
return;
} threadclient = new Thread(recv); threadclient.IsBackground = true; threadclient.Start();
}
}
接收消息:
// 接收服务端发来信息的方法
private void recv()//
{
while (true)//持续监听服务端发来的消息
{
try
{
//定义一个1M的内存缓冲区,用于临时性存储接收到的消息
byte[] arrRecvmsg = new byte[ * ]; //将客户端套接字接收到的数据存入内存缓冲区,并获取长度
int length = socketclient.Receive(arrRecvmsg); //将套接字获取到的字符数组转换为人可以看懂的字符串
string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, , length); this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strRevMsg, IdentityName = socketclient.RemoteEndPoint.ToString() });
});
}
catch (Exception ex)
{
MessageBox.Show("远程服务器已经中断连接" + ex.Message);
break;
}
}
}
发送消息:
private void send_Click(object sender, RoutedEventArgs e)
{
string strRevMsg = this.message.Text;
this.message.Clear(); lock (lockPool)
{
MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strRevMsg, IdentityName = "我(" + socketclient.LocalEndPoint.ToString() + ")" });
} //将输入的内容字符串转换为机器可以识别的字节数组
byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(strRevMsg);
//调用客户端套接字发送字节数组
socketclient.Send(arrClientSendMsg);
}
经过和同事的测试,可以实现简单的文字聊天,此代码仅为测试代码,若要用于实际的项目中,需要很大改进,比如socket异步建立,消息接收和发送等等。
基于socket实现的简单的聊天程序的更多相关文章
- [JavaWeb基础] 024.Socket编程之简单的聊天程序
1.Socket的简介 1)什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket ...
- python socket编程 实现简单p2p聊天程序
目标是写一个python的p2p聊天的项目,这里先说一下python socket的基础课程 一.Python Socket 基础课程 Socket就是套接字,作为BSD UNIX的进程通信机制,取后 ...
- Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程
SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程.在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被 ...
- 简单的聊天程序,主要用到的是Socket
服务端: import java.io.*; import java.net.*; import java.util.*; public class ChatServer { boolean stat ...
- C#编写简单的聊天程序
这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...
- C#编写简单的聊天程序(转)
这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...
- 使用Ajax long polling实现简单的聊天程序
关于web实时通信,通常使用长轮询或这长连接方式进行实现. 为了能够实际体会长轮询,通过Ajax长轮询实现了一个简单的聊天程序,在此作为笔记. 长轮询 传统的轮询方式是,客户端定时(一般使用setIn ...
- Java网络编程以及简单的聊天程序
网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...
- Udp实现简单的聊天程序
在<UDP通讯协议>这篇文章中,简单的说明了Udp协议特征及如何Udp协议传输数据 这里将用Udp协议技术,编写一个简单的聊天程序: //发送端: package com.shindo.j ...
随机推荐
- POJ 1021 2D-Nim
Description The 2D-Nim board game is played on a grid, with pieces on the grid points. On each move, ...
- solr6.6教程-从mysql数据库中导入数据(三)
整理多半天的solr6.6,终于算是把solr6.6中配置数据库弄出来了,网上的文章千篇一律,各说个的,没有一篇统一覆盖solr6.6版本配置的 帖子,本章节我会把配置的一些注意事项一一列举,由于时间 ...
- try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会 不会被执行,什么时候被执行,在 return 前还是后?
这是一道面试题,首先finally{}里面的code肯定是会执行的,至于在return前还是后, 看答案说的是在return后执行,我觉得不对,百度了一下,有说return前的,有说return后的, ...
- Linux服务器上安装MySql数据库(默认安装,密码为空),首次使用需要修改密码
1,在/etc/my.cnf末尾 加入skip-grant-tables,保存,跳过身份验证. 2,重启MySql,使刚才修改的配置生效. 3,终端输入mysql,然后再输入use mysql; 4 ...
- java网络编程(2)——UDP与TCP
首先,先介绍这两种协议: UDP:UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互 ...
- JQuery基础知识学习1
1.JQuery是javascript的类库 2.下载JQuery 3.导入JQuery <script src="jquery-3.0.0.js"></scri ...
- CentOS下iptables持久化
iptables规则持久化 设定防火墙规则 iptables -A INPUT -s 1.1.1.1/32 -p tcp -m tcp --dport 22 -j DROP iptables -A I ...
- Storm+HBase实时实践
1.HBase Increment计数器 hbase counter的原理: read+count+write,正好完成,就是讲key的value读出,若存在,则完成累加,再写入,若不存在,则按&qu ...
- jquery 图片转为base64
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- css进行中打点效果
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...