客户端与服务器通信_java客户端与服务器端通信 - CSDN
精华内容
参与话题
  • 客户端与服务器通信

    2018-10-20 15:19:30
    客户端与服务器端的通信过程,包括读信息和写信息,对于客户端服务器端,如果将数据传给对方,就称为写,用到输出流;反之,如果从对方处得到数据,就为读,用到输入流。 TCP编程中,客户端服务器端之间的通信是...

    如何实现双向聊天?

    客户端与服务器端的通信过程,包括读信息和写信息,对于客户端和服务器端,如果将数据传给对方,就称为写,用到输出流;反之,如果从对方处得到数据,就为读,用到输入流。
    TCP编程中,客户端和服务器端之间的通信是通过Socket实现的。

    如何向对方发送信息?
    从java.net.Socket文档中,会发现其中有一个重要函数:
    public OutputStream getOutputStream() throws IOException//打开此Socket的输出流。
    for example:

    Socket socket = new Socket("192.168.32.1",8080);
    OutputStream os = socket.getOutputStream();
    
    

    如何从对方处接收信息?
    打开java.net.Socket文档,会发现其中有一个重要函数:
    public InputStream getInputStream() throws IOException//打开此Socket的输入流。
    for example:

    Socket socket = new Socket("192.168.32.1",8080);
    InputStream is = socket.getInputStream(); // 得到输入流
    

    明显,实现客户端和服务器端的通信,既需要读操作,也需要写操作。

    服务器端代码:

    package chat2;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server {
    
    	public static void main(String[] args) throws Exception {
    		ServerSocket ss = new ServerSocket(8080);
    		Socket s = ss.accept();
    		
    		//获取对方传递过来的消息并打印
    		InputStream in = s.getInputStream();
    		BufferedReader br = new BufferedReader(new InputStreamReader(in));
    		String str = br.readLine();//读
    		System.out.println(str);
    	}
    
    }
    
    

    客户端代码:

    package chat2;
    
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class Client {
    
    	public static void main(String[] args) throws Exception {
    		Socket socket = new Socket("192.168.32.1",8080);
    		OutputStream os = socket.getOutputStream();//os只能发字节数组
    		PrintStream ps = new PrintStream(os);//ps功能更强大
    		ps.println("服务器,你好!");//信息发送出去
    	}
    
    }
    
    
    展开全文
  • 现在结和我所学,我想总结一下客户端服务器端的通信过程。只有明白了原理,我们才会明白当我们程序开发过程中错误的问题会出现在那,才会更好的解决问题。  我们首先要了解一个概念性的词汇:Socket  socket的...

      学习任何东西,我们只要搞清楚其原理,就会触类旁通。现在结和我所学,我想总结一下客户端到服务器端的通信过程。只有明白了原理,我们才会明白当我们程序开发过程中错误的问题会出现在那,才会更好的解决问题。

        我们首先要了解一个概念性的词汇:Socket

        socket的英文原义是“孔”或“插座”。作为进程通信机制,取后一种意思。通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。(其实就是两个程序通信用的。)socket非常类似于电话的插座。以一个电话网为例。电话的通话双方相当于相互通信的2个程序,电话号码可以当作是IP地址。任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;同时要知道对方的号码(IP地址),相当于对方有一个固定的socket。然后向对方拨号呼叫,相当于发出连接请求。对方假如在场并空闲,拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机相当于关闭socket,撤消连接,通信完成。

        以上通信是以两个人通话做为事例来在概的说明了下通信,但是现在假如通信中的一个人是外国人(说英语),一个人是中国人(说普通话),他们俩相互通信的话,都不能听明白对方说的是什么,那么他们的沟通就不能够完成。但是如果我们给一个规定,给通话双方,只能讲普通话,那么双方沟通就没有障碍了。这就引出来了通信协议。

    有两种类型:(Tcp协议与Udp协议):

    Tcp协议与Udp协议是在两硬件设备上进行通信传输的一种数据语法。

    – 流式Socket(STREAM):

        是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低;Tcp:是以流的形式来传的。

    – 数据报式Socket(DATAGRAM):

        是一种无连接的Socket,对应于无连接的UDP服务应用.不安全(丢失,顺序混乱,在接收端要分析重排及要求重发),但效率高.Udp:将数据包拆开为若干份编号后来传输。在传输的过程中容易出现数据的丢失。但是传输速度要比TCP的快。

    Socket的通信流程

    • Demo:

    • 服务器端:

    – 申请一个socket (socketWatch)用来监听的

    – 绑定到一个IP地址和一个端口上

    – 开启侦听,等待接授客户端的连接

    – 当有连接时创建一个用于和连接进来的客户端进行通信的socket(socketConnection)

    – 即续监听,等侍下一个客户的连接

    代码如下:

    
     
    1. using System;

    2. using System.Collections.Generic;

    3. using System.ComponentModel;

    4. using System.Data;

    5. using System.Drawing;

    6. using System.Linq;

    7. using System.Text;

    8. using System.Windows.Forms;

    9.  
    10. using System.Net;//IPAdress,IPEndPoint(ip和端口)类

    11. using System.Net.Sockets;

    12. using System.Threading;

    13. using System.IO;

    14.  
    15. namespace MyChatRoomServer

    16. {

    17. public partial class FChatServer : Form

    18. {

    19. public FChatServer()

    20. {

    21. InitializeComponent();

    22. TextBox.CheckForIllegalCrossThreadCalls = false;//关闭 对 文本框 的跨线程操作检查

    23. }

    24.  
    25. Thread threadWatch = null;//负责监听 客户端 连接请求的 线程

    26. Socket socketWatch = null;//负责监听的 套接字

    27.  
    28. private void btnBeginListen_Click(object sender, EventArgs e)

    29. {

    30. //创建 服务端 负责监听的 套接字,参数(使用IP4寻址协议,使用流式连接,使用TCP协议传输数据)

    31. socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    32. //获得文本框中的 IP地址对象

    33. IPAddress address = IPAddress.Parse(txtIP.Text.Trim());

    34. //创建 包含 ip 和 port 的网络节点对象

    35. IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));

    36. //将 负责监听 的套接字 绑定到 唯一的IP和端口上

    37. socketWatch.Bind(endpoint);

    38. //设置监听队列的长度

    39. socketWatch.Listen(10);

    40.  
    41. //创建 负责监听的线程,并传入监听方法

    42. threadWatch = new Thread(WatchConnecting);

    43. threadWatch.IsBackground = true;//设置为后台线程

    44. threadWatch.Start();//开启线程

    45. ShowMsg("服务器启动监听成功~");

    46. //IPEndPoint

    47. //socketWatch.Bind(

    48. }

    49. //保存了服务器端 所有负责和客户端通信的套接字

    50. Dictionary<string, Socket> dict = new Dictionary<string, Socket>();

    51. //保存了服务器端 所有负责调用 通信套接字.Receive方法 的线程

    52. Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

    53.  
    54. //Socket sokConnection = null;

    55. /// <summary>

    56. /// 监听客户端请求的方法

    57. /// </summary>

    58. void WatchConnecting()

    59. {

    60. while (true)//持续不断的监听新的客户端的连接请求

    61. {

    62. //开始监听 客户端 连接请求,注意:Accept方法,会阻断当前的线程!

    63. Socket sokConnection = socketWatch.Accept();//一旦监听到客户端的请求,就返回一个负责和该客户端通信的套接字 sokConnection

    64. //sokConnection.Receive

    65. //向 列表控件中 添加一个 客户端的ip端口字符串,作为客户端的唯一标识

    66. lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());

    67. //将 与客户端通信的 套接字对象 sokConnection 添加到 键值对集合中,并以客户端IP端口作为键

    68. dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);

    69.  
    70. //创建 通信线程

    71. ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);

    72. Thread thr = new Thread(pts);

    73. thr.IsBackground = true;//设置为

    74. thr.Start(sokConnection);//启动线程 并为线程要调用的方法RecMsg 传入参数sokConnection

    75.  
    76. dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr);//将线程 保存在 字典里,方便大家以后做“踢人”功能的时候用

    77.  
    78. ShowMsg("客户端连接成功!" + sokConnection.RemoteEndPoint.ToString());

    79. //sokConnection.RemoteEndPoint 中保存的是 当前连接客户端的 Ip和端口

    80. }

    81. }

    82.  
    83. /// <summary>

    84. /// 服务端 负责监听 客户端 发送来的数据的 方法

    85. /// </summary>

    86. void RecMsg(object socketClientPara)

    87. {

    88. Socket socketClient = socketClientPara as Socket;

    89. while (true)

    90. {

    91. //定义一个 接收用的 缓存区(2M字节数组)

    92. byte[] arrMsgRec = new byte[1024 * 1024 * 2];

    93. //将接收到的数据 存入 arrMsgRec 数组,并返回 真正接收到的数据 的长度

    94. int length=-1;

    95. try

    96. {

    97. length = socketClient.Receive(arrMsgRec);

    98. }

    99. catch (SocketException ex)

    100. {

    101. ShowMsg("异常:" + ex.Message);

    102. //从 通信套接字 集合中 删除 被中断连接的 通信套接字对象

    103. dict.Remove(socketClient.RemoteEndPoint.ToString());

    104. //从 通信线程 结合中 删除 被终端连接的 通信线程对象

    105. dictThread.Remove(socketClient.RemoteEndPoint.ToString());

    106. //从 列表中 移除 被中断的连接 ip:Port

    107. lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString());

    108. break;

    109. }

    110. catch (Exception ex)

    111. {

    112. ShowMsg("异常:" + ex.Message);

    113. break;

    114. }

    115. if (arrMsgRec[0] == 0)//判断 发送过来的数据 的第一个元素是 0,则代表发送来的是 文字数据

    116. {

    117. //此时 是将 数组 所有的元素 都转成字符串,而真正接收到的 只有服务端发来的几个字符

    118. string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,1, length-1);

    119. ShowMsg(strMsgRec);

    120. }

    121. else if (arrMsgRec[0] == 1)//如果是1 ,则代表发送过来的是 文件数据(图片/视频/文件....)

    122. {

    123. SaveFileDialog sfd = new SaveFileDialog();//保存文件选择框对象

    124. if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)//用户选择文件路径后

    125. {

    126. string fileSavePath = sfd.FileName;//获得要保存的文件路径

    127. //创建文件流,然后 让文件流来 根据路径 创建一个文件

    128. using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))

    129. {

    130. fs.Write(arrMsgRec, 1, length-1);

    131. ShowMsg("文件保存成功:" + fileSavePath);

    132. }

    133. }

    134. }

    135. }

    136. }

    137.  
    138. //发送消息到客户端

    139. private void btnSend_Click(object sender, EventArgs e)

    140. {

    141. if (string.IsNullOrEmpty(lbOnline.Text))

    142. {

    143. MessageBox.Show("请选择要发送的好友");

    144. }

    145. else

    146. {

    147. string strMsg = txtMsgSend.Text.Trim();

    148. //将要发送的字符串 转成 utf8对应的字节数组

    149. byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);

    150. //获得列表中 选中的KEY

    151. string strClientKey = lbOnline.Text;

    152. //通过key,找到 字典集合中对应的 与某个客户端通信的 套接字的 send方法,发送数据给对方

    153. try

    154. {

    155. dict[strClientKey].Send(arrMsg);

    156. //sokConnection.Send(arrMsg);

    157. ShowMsg("发送了数据出去:" + strMsg);

    158. }

    159. catch (SocketException ex)

    160. {

    161. ShowMsg("发送时异常:"+ex.Message);

    162. }

    163. catch (Exception ex)

    164. {

    165. ShowMsg("发送时异常:" + ex.Message);

    166. }

    167. }

    168. }

    169.  
    170. //服务端群发消息

    171. private void btnSendToAll_Click(object sender, EventArgs e)

    172. {

    173. string strMsg = txtMsgSend.Text.Trim();

    174. //将要发送的字符串 转成 utf8对应的字节数组

    175. byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);

    176. foreach (Socket s in dict.Values)

    177. {

    178. s.Send(arrMsg);

    179. }

    180. ShowMsg("群发完毕!:)");

    181. }

    182.  
    183. #region 显示消息

    184. /// <summary>

    185. /// 显示消息

    186. /// </summary>

    187. /// <param name="msg"></param>

    188. void ShowMsg(string msg)

    189. {

    • 客户端:

    – 申请一个socket(socketClient)

    – 连接服务器(指明IP地址和端口号)

    代码如下:

    
     
    1. using System;

    2.  
    3. using System.Collections.Generic;

    4.  
    5. using System.ComponentModel;

    6.  
    7. using System.Data;

    8.  
    9. using System.Drawing;

    10.  
    11. using System.Linq;

    12.  
    13. using System.Text;

    14.  
    15. using System.Windows.Forms;

    16.  
    17. using System.Net.Sockets;

    18.  
    19. using System.Net;

    20.  
    21. using System.Threading;

    22.  
    23. namespace MyChatRoomClient

    24.  
    25. {

    26.  
    27. public partial class FChatClient : Form

    28.  
    29. {

    30.  
    31. public FChatClient()

    32.  
    33. {

    34.  
    35. InitializeComponent();

    36.  
    37. TextBox.CheckForIllegalCrossThreadCalls = false;

    38.  
    39. }

    40.  
    41. Thread threadClient = null; //客户端 负责 接收 服务端发来的数据消息的线程

    42.  
    43. Socket socketClient = null;//客户端套接字

    44.  
    45. //客户端发送连接请求到服务器

    46.  
    47. private void btnConnect_Click(object sender, EventArgs e)

    48.  
    49. {

    50.  
    51. IPAddress address = IPAddress.Parse(txtIP.Text.Trim());//获得IP

    52.  
    53. IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));//网络节点

    54.  
    55. //创建客户端套接字

    56.  
    57. socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    58.  
    59. //向 指定的IP和端口 发送连接请求

    60.  
    61. socketClient.Connect(endpoint);

    62.  
    63. //客户端 创建线程 监听服务端 发来的消息

    64.  
    65. threadClient = new Thread(RecMsg);

    66.  
    67. threadClient.IsBackground = true;

    68.  
    69. threadClient.Start();

    70.  
    71. }

    72.  
    73. /// <summary>

    74.  
    75. /// 监听服务端 发来的消息

    76.  
    77. /// </summary>

    78.  
    79. void RecMsg()

    80.  
    81. {

    82.  
    83. while (true)

    84.  
    85. {

    86.  
    87. //定义一个 接收用的 缓存区(2M字节数组)

    88.  
    89. byte[] arrMsgRec = new byte[1024 * 1024 * 2];

    90.  
    91. //将接收到的数据 存入 arrMsgRec 数组,并返回 真正接收到的数据 的长度

    92.  
    93. int length= socketClient.Receive(arrMsgRec);

    94.  
    95. //此时 是将 数组 所有的元素 都转成字符串,而真正接收到的 只有服务端发来的几个字符

    96.  
    97. string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);

    98.  
    99. ShowMsg(strMsgRec);

    100.  
    101. }

    102.  
    103. }

    104.  
    105. void ShowMsg(string msg)

    106.  
    107. {

    108.  
    109. txtMsg.AppendText(msg + "\r\n");

    110.  
    111. }

    112.  
    113. }

    114.  
    115. }

    通信过程图

    通过以上流程图我们可以看出,客户端与服务器端之间的一个基本通信流程,概括一下Socket 一般应用模式(客户端和服务器端)的作用:

    服务器端:最少有两个socket,一个是服务端负责监听客户端发来连接请求,但不负责与请求的客户端通信,另一个是每当服务器端成功接收到客户端时,但在服务器端创建一个用与请求的客户端进行通信的socket.

    客户端:指定要连接的服务器端地址和端口,通过创建一个socket对象来初始化一个到服务器端的TCP连接。

    转载自:http://www.codeceo.com/article/client-to-server.html

    展开全文
  • 现在结和我所学,我想总结一下客户端服务器端的通信过程。只有明白了原理,我们才会明白当我们程序开发过程中错误的问题会出现在那,才会更好的解决问题。  我们首先要了解一个概念性的词汇:Socket  socket的...

        学习任何东西,我们只要搞清楚其原理,就会触类旁通。现在结和我所学,我想总结一下客户端到服务器端的通信过程。只有明白了原理,我们才会明白当我们程序开发过程中错误的问题会出现在那,才会更好的解决问题。

        我们首先要了解一个概念性的词汇:Socket

        socket的英文原义是“孔”或“插座”。作为进程通信机制,取后一种意思。通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。(其实就是两个程序通信用的。)socket非常类似于电话的插座。以一个电话网为例。电话的通话双方相当于相互通信的2个程序,电话号码可以当作是IP地址。任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;同时要知道对方的号码(IP地址),相当于对方有一个固定的socket。然后向对方拨号呼叫,相当于发出连接请求。对方假如在场并空闲,拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机相当于关闭socket,撤消连接,通信完成。

        以上通信是以两个人通话做为事例来在概的说明了下通信,但是现在假如通信中的一个人是外国人(说英语),一个人是中国人(说普通话),他们俩相互通信的话,都不能听明白对方说的是什么,那么他们的沟通就不能够完成。但是如果我们给一个规定,给通话双方,只能讲普通话,那么双方沟通就没有障碍了。这就引出来了通信协议。

    有两种类型:(Tcp协议与Udp协议):

    Tcp协议与Udp协议是在两硬件设备上进行通信传输的一种数据语法。

    – 流式Socket(STREAM):

        是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低;Tcp:是以流的形式来传的。

    – 数据报式Socket(DATAGRAM):

        是一种无连接的Socket,对应于无连接的UDP服务应用.不安全(丢失,顺序混乱,在接收端要分析重排及要求重发),但效率高.Udp:将数据包拆开为若干份编号后来传输。在传输的过程中容易出现数据的丢失。但是传输速度要比TCP的快。

    Socket的通信流程

    • Demo:

    • 服务器端:

    – 申请一个socket (socketWatch)用来监听的

    – 绑定到一个IP地址和一个端口上

    – 开启侦听,等待接授客户端的连接

    – 当有连接时创建一个用于和连接进来的客户端进行通信的socket(socketConnection)

    – 即续监听,等侍下一个客户的连接

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    using System.Net;//IPAdress,IPEndPoint(ip和端口)类
    using System.Net.Sockets;
    using System.Threading;
    using System.IO;
    
    namespace MyChatRoomServer
    {
        public partial class FChatServer : Form
        {
            public FChatServer()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;//关闭 对 文本框  的跨线程操作检查
            }
    
            Thread threadWatch = null;//负责监听 客户端 连接请求的 线程
            Socket socketWatch = null;//负责监听的 套接字
    
            private void btnBeginListen_Click(object sender, EventArgs e)
            {
                //创建 服务端 负责监听的 套接字,参数(使用IP4寻址协议,使用流式连接,使用TCP协议传输数据)
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
               //获得文本框中的 IP地址对象
                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                //创建 包含 ip 和 port 的网络节点对象
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
                //将 负责监听 的套接字 绑定到 唯一的IP和端口上
                socketWatch.Bind(endpoint);
                //设置监听队列的长度
                socketWatch.Listen(10);
    
                //创建 负责监听的线程,并传入监听方法
                threadWatch = new Thread(WatchConnecting);
                threadWatch.IsBackground = true;//设置为后台线程
                threadWatch.Start();//开启线程
                ShowMsg("服务器启动监听成功~");
                //IPEndPoint 
                //socketWatch.Bind(
            }
            //保存了服务器端 所有负责和客户端通信的套接字
            Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
            //保存了服务器端 所有负责调用 通信套接字.Receive方法 的线程
            Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
    
            //Socket sokConnection = null;
            /// <summary>
            /// 监听客户端请求的方法
            /// </summary>
            void WatchConnecting()
            {
                while (true)//持续不断的监听新的客户端的连接请求
                {
                    //开始监听 客户端 连接请求,注意:Accept方法,会阻断当前的线程!
                    Socket sokConnection = socketWatch.Accept();//一旦监听到客户端的请求,就返回一个负责和该客户端通信的套接字 sokConnection
                    //sokConnection.Receive
                    //向 列表控件中 添加一个 客户端的ip端口字符串,作为客户端的唯一标识
                    lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());
                    //将 与客户端通信的 套接字对象 sokConnection 添加到 键值对集合中,并以客户端IP端口作为键
                    dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);
    
                    //创建 通信线程
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);
                    Thread thr = new Thread(pts);
                    thr.IsBackground = true;//设置为
                    thr.Start(sokConnection);//启动线程 并为线程要调用的方法RecMsg 传入参数sokConnection
    
                    dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr);//将线程 保存在 字典里,方便大家以后做“踢人”功能的时候用
    
                    ShowMsg("客户端连接成功!" + sokConnection.RemoteEndPoint.ToString());
                    //sokConnection.RemoteEndPoint 中保存的是 当前连接客户端的 Ip和端口
                }
            }
    
            /// <summary>
            /// 服务端 负责监听 客户端 发送来的数据的 方法
            /// </summary>
            void RecMsg(object socketClientPara)
            {
                Socket socketClient = socketClientPara as Socket;
                while (true)
                {
                    //定义一个 接收用的 缓存区(2M字节数组)
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    //将接收到的数据 存入 arrMsgRec 数组,并返回 真正接收到的数据 的长度
                    int length=-1;
                    try
                    {
                        length = socketClient.Receive(arrMsgRec);
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        //从 通信套接字 集合中 删除 被中断连接的 通信套接字对象
                        dict.Remove(socketClient.RemoteEndPoint.ToString());
                        //从 通信线程    结合中 删除 被终端连接的 通信线程对象
                        dictThread.Remove(socketClient.RemoteEndPoint.ToString());
                        //从 列表中 移除 被中断的连接 ip:Port
                        lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString());
                        break;
                    }
                    catch (Exception ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        break;
                    }
                    if (arrMsgRec[0] == 0)//判断 发送过来的数据 的第一个元素是 0,则代表发送来的是 文字数据
                    {
                        //此时 是将 数组 所有的元素 都转成字符串,而真正接收到的 只有服务端发来的几个字符
                        string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,1, length-1);
                        ShowMsg(strMsgRec);
                    }
                    else if (arrMsgRec[0] == 1)//如果是1 ,则代表发送过来的是 文件数据(图片/视频/文件....)
                    {
                        SaveFileDialog sfd = new SaveFileDialog();//保存文件选择框对象
                        if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)//用户选择文件路径后
                        {
                            string fileSavePath = sfd.FileName;//获得要保存的文件路径
                            //创建文件流,然后 让文件流来 根据路径 创建一个文件
                            using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                            {
                                fs.Write(arrMsgRec, 1, length-1);
                                ShowMsg("文件保存成功:" + fileSavePath);
                            }
                        }
                    }
                }
            }
    
            //发送消息到客户端
            private void btnSend_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(lbOnline.Text))
                {
                    MessageBox.Show("请选择要发送的好友");
                }
                else
                {
                    string strMsg = txtMsgSend.Text.Trim();
                    //将要发送的字符串 转成 utf8对应的字节数组
                    byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                    //获得列表中 选中的KEY
                    string strClientKey = lbOnline.Text;
                    //通过key,找到 字典集合中对应的 与某个客户端通信的 套接字的 send方法,发送数据给对方
                    try
                    {
                        dict[strClientKey].Send(arrMsg);
                        //sokConnection.Send(arrMsg);
                        ShowMsg("发送了数据出去:" + strMsg);
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("发送时异常:"+ex.Message);
                    }
                    catch (Exception ex)
                    {
                        ShowMsg("发送时异常:" + ex.Message);
                    }
                }
            }
    
            //服务端群发消息
            private void btnSendToAll_Click(object sender, EventArgs e)
            {
                string strMsg = txtMsgSend.Text.Trim();
                //将要发送的字符串 转成 utf8对应的字节数组
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                foreach (Socket s in dict.Values)
                {
                    s.Send(arrMsg);
                }
                ShowMsg("群发完毕!:)");
            }
    
            #region 显示消息
            /// <summary>
            /// 显示消息
            /// </summary>
            /// <param name="msg"></param>
            void ShowMsg(string msg)
            {
    • 客户端:

    – 申请一个socket(socketClient)

    – 连接服务器(指明IP地址和端口号)

    代码如下:

    using System;
    
    using System.Collections.Generic;
    
    using System.ComponentModel;
    
    using System.Data;
    
    using System.Drawing;
    
    using System.Linq;
    
    using System.Text;
    
    using System.Windows.Forms;
    
    using System.Net.Sockets;
    
    using System.Net;
    
    using System.Threading;
    
    namespace MyChatRoomClient
    
    {
    
        public partial class FChatClient : Form
    
        {
    
            public FChatClient()
    
            {
    
                InitializeComponent();
    
                TextBox.CheckForIllegalCrossThreadCalls = false;
    
            }
    
            Thread threadClient = null; //客户端 负责 接收 服务端发来的数据消息的线程
    
            Socket socketClient = null;//客户端套接字
    
    //客户端发送连接请求到服务器
    
            private void btnConnect_Click(object sender, EventArgs e)
    
            {
    
                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());//获得IP
    
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));//网络节点
    
    //创建客户端套接字
    
                socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                //向 指定的IP和端口 发送连接请求
    
                socketClient.Connect(endpoint);
    
                //客户端 创建线程 监听服务端 发来的消息
    
                threadClient = new Thread(RecMsg);
    
                threadClient.IsBackground = true;
    
                threadClient.Start();
    
            }
    
            /// <summary>
    
    /// 监听服务端 发来的消息
    
    /// </summary>
    
            void RecMsg()
    
            {
    
                while (true)
    
                {
    
                    //定义一个 接收用的 缓存区(2M字节数组)
    
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
    
                    //将接收到的数据 存入 arrMsgRec 数组,并返回 真正接收到的数据 的长度
    
                   int length=  socketClient.Receive(arrMsgRec);
    
                    //此时 是将 数组 所有的元素 都转成字符串,而真正接收到的 只有服务端发来的几个字符
    
                   string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);
    
                    ShowMsg(strMsgRec);
    
                }
    
            }
    
            void ShowMsg(string msg)
    
            {
    
                txtMsg.AppendText(msg + "\r\n");
    
            }
    
        }
    
    }

    通信过程图

    通过以上流程图我们可以看出,客户端与服务器端之间的一个基本通信流程,概括一下Socket 一般应用模式(客户端和服务器端)的作用:

    服务器端:最少有两个socket,一个是服务端负责监听客户端发来连接请求,但不负责与请求的客户端通信,另一个是每当服务器端成功接收到客户端时,但在服务器端创建一个用与请求的客户端进行通信的socket.

    客户端:指定要连接的服务器端地址和端口,通过创建一个socket对象来初始化一个到服务器端的TCP连接。

    转载自:http://www.codeceo.com/article/client-to-server.html

    展开全文
  • 客户端与服务器通信方式总结

    千次阅读 2013-10-29 16:22:02
    HTTP:客户端发出请求、服务器端响应的方式.单工 基于客户端 comet :基于 HTTP 长连接的“服务器推”技术:基于 AJAX 的长轮询方式;基于 iframe 及 htmlfile 的流方式 websocket

                                      客户端与服务器端通信方式总结

    1.HTTP:客户端发出请求、服务器端响应的方式.

    2.基于客户端套接口的“服务器推”技术

    (1)Flash XMLSocket

    如果Web应用的用户接受应用只有在安装了 Flash 播放器才能正常运行, 那么使用 Flash 的 XMLSocket 也是一个可行的方案。

    这种方案实现的基础是:Flash 提供了 XMLSocket 类;javaScript 和 Flash 的紧密结合:在 JavaScript 可以直接调用 Flash 程序提供的接口。

    具体实现方法:在 HTML 页面中内嵌入一个使用了 XMLSocket 类的 Flash 程序。JavaScript通过调用此Flash程序提供的套接口接口与服务器端的套接口进行通信。JavaScript 在收到服务器端以XML格式传送的信息后可以很容易地控制 HTML页面的内容显示。

    (2)Java Applet 套接口

    在客户端使用Java Applet,通过java.net.Socketjava.net.DatagramSocket 或 java.net.MulticastSocket建立与服务器端的套接口连接,从而实现“服务器推”。这种方案最大的不足在于Java applet在收到服务器端返回的信息后,无法通过 JavaScript去更新HTML页面的内容。

    3.AJAX技术:“Asynchronous JavaScript and XML”(异步JavaScriptXML)

    XmlHttpRequest使客户端可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。JavaScript可以调用XMLHttpRequest对象发出 HTTP 请求,JavaScript响应处理函数根据服务器返回的信息(不是整个网页,只是部分信息)对 HTML 页面的显示进行更新。


    图 1.传统的 Web 应用模型与基于 AJAX 的模型之比较


    4.comet :基于 HTTP 长连接的“服务器推”技术

    (1)基于 AJAX 的长轮询方式

    使用 AJAX 实现服务器推与传统的 AJAX 应用不同之处在于:

       1.1服务器端会阻塞请求直到有数据传递或超时才返回。

               1.2客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。

               1.3当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所                   有的信息取回

    // JavaScript 文件
    var http_request = false;
    function send_request(url) {
        //初始化,指定处理函数,发送请求的函数 
        http_request = false;
        //开始初始化XMLHttpRequest对象 
        if (window.XMLHttpRequest) {
            //Mozilla 浏览器 
            http_request = new XMLHttpRequest();
            if (http_request.overrideMimeType) {
                //设置MiME类别 
                http_request.overrideMimeType('text/xml');
            }
        }
        else if (window.ActiveXObject) {
            // IE浏览器 
            try {
                http_request = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (e) {
                try {
                    http_request = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch (e) { }
            }
        }
        if (!http_request) {
            // 异常,创建对象实例失败 
            window.alert("不能创建XMLHttpRequest对象实例.");
            return false;
        }
        http_request.onreadystatechange = processRequest;
        // 确定发送请求的方式和URL以及是否同步执行下段代码 
        http_request.open("GET", url, true);
        http_request.send(null);
    }
    // 处理返回信息的函数
    function processRequest() {
        if (http_request.readyState == 4) {
            // 判断对象状态 
            // alert(http_request.readyState);
            // alert(http_request.status);
            if (http_request.status == 200) {
                // 信息已经成功返回,开始处理信息 
                Image1.ImageUrl = "GobangDisplay.aspx?cs=" + DateTime.Now.Second.ToString();
                window.open('GobangDisplay.aspx', '_blank');
              //  document.getElementById("stateView").innerHTML = s;
                // alert(str);
              //  showMsg(str);
            }
            else {
                //页面不正常 
                alert(http_request.status + "您所请求的页面有异常.");
            }
        }
    }

    图 2. 基于长轮询的服务器推模型


    (2)基于 iframe 及 htmlfile 的流方式

        iframe 是很早就存在的一种 HTML 标记, 通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。

    Tip不要在同一客户端同时使用超过两个的 HTTP 长连接

    我们使用 IE 下载文件时会有这样的体验,从同一个 Web 服务器下载文件,最多只能有两个文件同时被下载。第三个文件的下载会被阻塞,直到前面下载的文件下载完毕。     这是因为 HTTP 1.1 规范中规定,客户端不应该与服务器端建立超过两个的 HTTP 连接, 新的连接会被阻塞。而 IE 在实现中严格遵守了这种规定。

    详细链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

    5.websocket

         WebSocket 规范的目标是在浏览器中实现和服务器端双向通信。浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:互相沟通的Header是很小的-大概只2Bytes、服务器可以主动传送数据给客户端。目前还只有部分浏览器支持此协议。

     





    展开全文
  • 在Web项目中,要实现客户端与服务端的交互,可通过cookie、隐藏框架、HTTP...浏览器向服务器发送请求时,为这个服务器存储的cookie会其他信息一起发送到服务器。这使得JavaScript可以在客户端设置一个cookie,之后
  • 客户端与服务器的数据传输

    万次阅读 2018-06-29 15:53:21
    1.Socket网络编程之传递字符类型(图解编码)2015年05月09日 09:50:42阅读数:1886Java最初是作为网络编程语言出现的,它对网络的高度支持,使得客户端服务器流畅的沟通变成现实。而在网络编程中,使用最多的就是...
  • 用Python的openpyxl库导出xlsx表格,在导入SPSS时,一直在等待,然后最后显示“发生严重错误客户端无法再与服务器通信”,无法导入数据,并且SPSS要重开才能使用 办法: 用MATLAB,导入excel表格,然后再导出excel,...
  • 客户端与服务端Socket通信原理详解

    万次阅读 2020-10-03 20:27:10
    首先ServerSocket将在服务端监听某个端口,当发现客户端有Socket来试图连接它时,它会accept该Socket的连接请求,同时在服务端建立一个对应的Socket之进行通信。这样就有两个Socket了,客户端...
  • C++ Socket多客户端服务器通信

    千次阅读 热门讨论 2019-12-11 16:38:47
    关于Socket通信主要采用了C++编程,实现多线程通信,多个客户端同时和服务器通信,并支持服务器以广播的形式向所有客户端发送消息,该历程未加界面。具体的细节和源码见下分析 2 执行流程 服务器端 运行程序后...
  • 客户端服务器之间通信讲解

    万次阅读 2016-09-08 09:52:26
     服务器:能接收客户端发来的请求,并能发送数据给客户端以做出回应。 从这里可以看出,我们的电脑可以充当双重角色。 1、当我们用浏览器浏览网页,要查看某个文件时,我们的电脑会发出请求给文件服务器,...
  • Java实现服务器客户端简单通信

    万次阅读 2019-06-16 10:25:21
    Java中网络编程这一块有封装的类库,使用简单,了解原理可以教容易实现服务器客户端的简单通信。在编程之前,首先要需要对TCP/IP协议有一定的了解,需要知道Socket套接字的作用以及用法,这个可以在API文档中去...
  • 服务器初始化 (1)调用socket,创建文件描述符 (2)调用bind,将文件描述符ip/port连接起来。若端口号已被占用,则bind失败 (3)调用listen,声明该文件描述符是服务器的一个文件描述符,为之后的accept做...
  • 参考:http://blog.csdn.net/hlhakey/article/details/47030295
  • 需求:客户端发送消息到服务器服务器接收到消息并读取输出,然后写出到客户端客户端接收到输出。 1、建立服务器端  |-服务器建立通信ServerSocket  |-服务器建立Socket接收客户端连接  |-建立IO输入流读取...
  • 1、sendto和recvfrom函数介绍 sendto(经socket传送数据) 相关函数 send , sendmsg,recv , recvfrom , socket 表头文件 #include #include ...int sendto ( int s , const void * msg, int l
  • 客户端并发访问的问题分析、多线程方式实现客户端并发访问、多进程方式实现客户端并发访问、解决多进程方式下僵尸进程问题
  • 一种客户端即时通信数据的加密和解密方法  摘要 本发明适用于即时通信领域,提供了一种客户端即时通信数据的加密和解密方法,所述方法包括以下步骤:A.客户端加密本地保存的即时通信数据,并将数据加密密钥...
  • 1:客户端程序 package com.pb.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.
  • socket实现聊天功能
  • 鉴于ServerSocket的accept方法是阻塞的,那么只能通过多线程的方式实现多客户端连接与服务器连接 基本步骤: 1,服务端创建ServerSocket绑定端口号,循环调用accept()方法 2,客户端创建一个socket并请求和服务器...
1 2 3 4 5 ... 20
收藏数 465,055
精华内容 186,022
关键字:

客户端与服务器通信