记得八年前第一次使用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实现的简单的聊天程序的更多相关文章

  1. [JavaWeb基础] 024.Socket编程之简单的聊天程序

    1.Socket的简介 1)什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket ...

  2. python socket编程 实现简单p2p聊天程序

    目标是写一个python的p2p聊天的项目,这里先说一下python socket的基础课程 一.Python Socket 基础课程 Socket就是套接字,作为BSD UNIX的进程通信机制,取后 ...

  3. Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

    SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程.在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被 ...

  4. 简单的聊天程序,主要用到的是Socket

    服务端: import java.io.*; import java.net.*; import java.util.*; public class ChatServer { boolean stat ...

  5. C#编写简单的聊天程序

    这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...

  6. C#编写简单的聊天程序(转)

    这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...

  7. 使用Ajax long polling实现简单的聊天程序

    关于web实时通信,通常使用长轮询或这长连接方式进行实现. 为了能够实际体会长轮询,通过Ajax长轮询实现了一个简单的聊天程序,在此作为笔记. 长轮询 传统的轮询方式是,客户端定时(一般使用setIn ...

  8. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  9. Udp实现简单的聊天程序

    在<UDP通讯协议>这篇文章中,简单的说明了Udp协议特征及如何Udp协议传输数据 这里将用Udp协议技术,编写一个简单的聊天程序: //发送端: package com.shindo.j ...

随机推荐

  1. 用Putty通过SSH访问Linux服务器

    1,sudo apt-get install ssh 2,sudo service ssh restart 3,重启ssh成功后,就可以直接用Putty访问服务器.

  2. 初学node.js有感一

    Node.js感悟 一.前言 很久以前就对node.js十分的好奇和感兴趣,因为种种原因没能去深入的认识了解和学习掌握这门技术,最近正好要做一些项目,其中就用到了node.js中的一些东西,所以借着使 ...

  3. 15-谜问题(深拷贝、LC检索、面向对象编程)

    问题描述: 在一个分成16格的方形棋盘上,放有15块编了号码的牌.对这些牌给定一种初始排列,要求通过一系列的合法移动将这一初始排列转换成目标排列. 这个问题解决时用到了L-C检索.在检索的过程中计算估 ...

  4. 《设计模式之禅》--设计模式大PK

    创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式. 其中单例模式要保持在内存中只有一个对象,原型模式是要求通过复制的方式产生一个新的对象. [工厂方法(抽象工厂) VS 建造者 ...

  5. UVA-818 dfs + 位运算

    暴力枚举一些圆环,将这些圆环解开,看能否成为单链.判断单链的三个条件: 除了这些删除的圆环之外,其他圆环还连接着的圆环不能超过两个. 剩下的环没有连成圈. 剩下的圆环共分成m堆,每堆之间无连接,m必须 ...

  6. nginx的环境配置的问题

    在安装好nginx之后,运行nginx,报错: nginx dyld: Library not loaded: /usr/local/lib/libpcre.1.dylib Referenced fr ...

  7. 高并发场景下的httpClient优化使用

    1.背景 我们有个业务,会调用其他部门提供的一个基于http的服务,日调用量在千万级别.使用了httpclient来完成业务.之前因为qps上不去,就看了一下业务代码,并做了一些优化,记录在这里. 先 ...

  8. 文本处理三剑客之grep&正则表达式

    grep是一个文本过滤工具,它支持正则表达式,能把搜索匹配到的行打印出来.grep的全称是Global Regular Expression Print(全局正则表达式)使用权限是所有用户. 一.gr ...

  9. MacOS App代码申请管理员权限

    原文: https://jacobpan3g.github.io/cn/2018/02/07/gain-root-permission-for-mac-app/,有问题欢迎在原文评论区一起讨论交流,我 ...

  10. 【前端】诸葛io收集前端js报错信息

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/zhuge_error.html 一.什么是诸葛io 诸葛io就是通过分析用户的操作事件对用户数据,行为路径等进行分 ...