基于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 ...
随机推荐
- OKL4虚拟化技术跟踪
这篇博客准备介绍OKL4的研究进展,本文的内容主要根据我个人阅读<OKL4_LongPaper_2010_HW_VM>这篇文章之后的理解,我也根据这篇论文的内容做了一些实验,奈何此论文涉及 ...
- bzoj 3166 [Heoi2013]Alo 可持久化Trie
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1227 Solved: 569[Submit][Status ...
- 函数重载overload
与void show(int a, char b, double c){}构成重载的有: a) void show(int x, char y, double z){} //no b) int sho ...
- python+flask:实现POST接口功能
1.首先需要安装python和flask,这个是必须的嘛. 2.我们这里实现的是一个POST功能的简单接口. from flask import Flask, request, jsonify imp ...
- day2(字符串、格式化输出、运算符、流程控制)
一.字符串 在Python中,加了引号的字符都被认为是字符串! 单引号.双引号.多引号的区别? 单引号和 双引号没有任何区别,但是某种情况下需要单双配合 如 msg = " My name ...
- 科普 TLS 1.3—新特性与开启方式
TLS 1.3 协议针对安全强化及效率提升等方面进行了大量修改,相继推出 20 多个草案版本,即将完成最终的标准化.标准完成后,OpenSSL 组织将推出 OpenSSL 1.1.1 版本,对 TLS ...
- linux iptables配置
防火墙硬件防火墙软件防火墙: 应用层防火墙 网络层防火墙:linux包过滤防火墙linux包过滤防火墙netfilter:位于linux内核中的包过滤功能体系,称为linux防火墙的"内核态 ...
- pycaffe︱caffe中fine-tuning模型三重天(函数详解、框架简述)
本文主要参考caffe官方文档[<Fine-tuning a Pretrained Network for Style Recognition>](http://nbviewer.jupy ...
- Java中list.get(index)报错
1.list.get(index)中的index为负值异常 严重:Exception occurred during processing request:-1 java.lang.ArrayInde ...
- 错误代码: 1449 The user specified as a definer ('root'@'%') does not exist
1. 错误描述 1 queries executed, 0 success, 1 errors, 0 warnings 查询:call analyse_use('20150501','20150601 ...