套接字编程.docx

上传人:b****5 文档编号:3412013 上传时间:2022-11-22 格式:DOCX 页数:18 大小:160.52KB
下载 相关 举报
套接字编程.docx_第1页
第1页 / 共18页
套接字编程.docx_第2页
第2页 / 共18页
套接字编程.docx_第3页
第3页 / 共18页
套接字编程.docx_第4页
第4页 / 共18页
套接字编程.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

套接字编程.docx

《套接字编程.docx》由会员分享,可在线阅读,更多相关《套接字编程.docx(18页珍藏版)》请在冰豆网上搜索。

套接字编程.docx

套接字编程

学习任何东西,我们只要搞清楚其原理,就会触类旁通。

现在结和我所学,我想总结一下客户端到服务器端的通信过程。

只有明白了原理,我们才会明白当我们程序开发过程中错误的问题会出现在那,才会更好的解决问题。

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

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

usingSystem;

usingSystem.Collections.Generic;

usingSystem.ComponentModel;

usingSystem.Data;

usingSystem.Drawing;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Windows.Forms;

 

usingSystem.Net;//IPAdress,IPEndPoint(ip和端口)类

usingSystem.Net.Sockets;

usingSystem.Threading;

usingSystem.IO;

 

namespaceMyChatRoomServer

{

    publicpartialclassFChatServer:

Form

    {

        publicFChatServer()

        {

            InitializeComponent();

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

        }

 

        ThreadthreadWatch=null;//负责监听客户端连接请求的线程

        SocketsocketWatch=null;//负责监听的套接字

 

        privatevoidbtnBeginListen_Click(objectsender,EventArgse)

        {

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

            socketWatch=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

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

            IPAddressaddress=IPAddress.Parse(txtIP.Text.Trim());

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

            IPEndPointendpoint=newIPEndPoint(address,int.Parse(txtPort.Text.Trim()));

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

            socketWatch.Bind(endpoint);

            //设置监听队列的长度

            socketWatch.Listen(10);

 

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

            threadWatch=newThread(WatchConnecting);

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

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

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

            //IPEndPoint

            //socketWatch.Bind(

        }

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

        Dictionarydict=newDictionary();

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

        DictionarydictThread=newDictionary();

 

        //SocketsokConnection=null;

        ///

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

        ///

        voidWatchConnecting()

        {

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

            {

                //开始监听客户端连接请求,注意:

Accept方法,会阻断当前的线程!

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

                //sokConnection.Receive

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

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

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

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

 

                //创建通信线程

                ParameterizedThreadStartpts=newParameterizedThreadStart(RecMsg);

                Threadthr=newThread(pts);

                thr.IsBackground=true;//设置为

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

 

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

 

                ShowMsg("客户端连接成功!

"+sokConnection.RemoteEndPoint.ToString());

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

            }

        }

 

        ///

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

        ///

        voidRecMsg(objectsocketClientPara)

        {

            SocketsocketClient=socketClientParaasSocket;

            while(true)

            {

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

                byte[]arrMsgRec=newbyte[1024*1024*2];

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

                intlength=-1;

                try

                {

                    length=socketClient.Receive(arrMsgRec);

                }

                catch(SocketExceptionex)

                {

                    ShowMsg("异常:

"+ex.Message);

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

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

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

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

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

Port

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

                    break;

                }

                catch(Exceptionex)

                {

                    ShowMsg("异常:

"+ex.Message);

                    break;

                }

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

                {

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

                    stringstrMsgRec=System.Text.Encoding.UTF8.GetString(arrMsgRec,1,length-1);

                    ShowMsg(strMsgRec);

                }

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

                {

                    SaveFileDialogsfd=newSaveFileDialog();//保存文件选择框对象

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

                    {

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

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

                        using(FileStreamfs=newFileStream(fileSavePath,FileMode.Create))

                        {

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

                            ShowMsg("文件保存成功:

"+fileSavePath);

                        }

                    }

                }

            }

        }

 

        //发送消息到客户端

        privatevoidbtnSend_Click(objectsender,EventArgse)

        {

            if(string.IsNullOrEmpty(lbOnline.Text))

            {

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

            }

            else

            {

                stringstrMsg=txtMsgSend.Text.Trim();

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

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

                //获得列表中选中的KEY

                stringstrClientKey=lbOnline.Text;

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

                try

                {

                    dict[strClientKey].Send(arrMsg);

                    //sokConnection.Send(arrMsg);

                    ShowMsg("发送了数据出去:

"+strMsg);

                }

                catch(SocketExceptionex)

                {

                    ShowMsg("发送时异常:

"+ex.Message);

                }

                catch(Exceptionex)

                {

                    ShowMsg("发送时异常:

"+ex.Message);

                }

            }

        }

 

        //服务端群发消息

        privatevoidbtnSendToAll_Click(objectsender,EventArgse)

        {

            stringstrMsg=txtMsgSend.Text.Trim();

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

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

            foreach(Socketsindict.Values)

            {

                s.Send(arrMsg);

            }

            ShowMsg("群发完毕!

)");

        }

 

        #region显示消息

        ///

        ///显示消息

        ///

        ///

        voidShowMsg(stringmsg)

        {

∙客户端:

– 申请一个socket(socketClient)

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

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

usingSystem;

 

usingSystem.Collections.Generic;

 

usingSystem.ComponentModel;

 

usingSystem.Data;

 

usingSystem.Drawing;

 

usingSystem.Linq;

 

usingSystem.Text;

 

usingSystem.Windows.Forms;

 

usingSystem.Net.Sockets;

 

usingSystem.Net;

 

usingSystem.Threading;

 

namespaceMyChatRoomClient

 

{

 

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1