Socket 编程
来源:互联网 发布:扫描仪软件打不开 编辑:程序博客网 时间:2024/06/08 11:27
分3个部分,首先介绍Socket基本概念(主要参考《Socket编程》);然后分别是基于MFC的Socket编程(参考《MFC socket网络编程(流程示例)》)和基于C#的Socket编程(参考《你得学会并且学得会的Socket编程基础知识》)
Socket是什么
如图1所示,传输控制协议/网间协议(TCP/IP)是一个工业标准的协议集,包含了运输层、网络层、链路层
Socket 是应用层与TCP/IP协议族通信的中间软件抽象层,将复杂的TCP/IP隐藏在一系列Socket接口后面
图1. Scoket抽象层
一次标准的Socket通信为(图2):
服务端首先初始化Socket,然后绑定并监听端口,阻塞直到有客户端连接,接着使用send和receive方法与客户端交互,最后关闭Socket;
客户端首先初始化Socket,然后根据Ip和端口与服务端连接,成功后通过send和receive方法与之交互,最后关闭Socket
图2. Socket通信
基于MFC的Socket编程
首先添加链接库:ws2_32.lib
服务端
- 加载套接字(socket)库
- 创建套接字
- 绑定套接字到本地地址和端口
- 将套接字设为监听模式
- 等待客户请求到来,当请求到来后接受并返回此次连接的套接字
- 使用上一步的套接字和客户端通信(send/recv)
- 关闭套接字
#include <Winsock2.h>//加裁头文件 #include <stdio.h>//加载标准输入输出头文件 void main(){ WORD wVersionRequested;//版本号 WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 );//1.1版本的套接字 err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; }//加载套接字库,加裁失败则返回 if ( LOBYTE( wsaData.wVersion ) != 1 ||HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; }//如果不是1.1的则退出 SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//创建套接字(socket)。 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//转换Unsigned short为网络字节序的格式 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //将套接字绑定到一个本地地址和端口上(bind) listen(sockSrv,5);//将套接字设为监听模式,准备接收客户请求(listen)。 SOCKADDR_IN addrClient;//定义地址族 int len=sizeof(SOCKADDR);//初始化这个参数,这个参数必须被初始化 while(1) { SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); //accept的第三个参数一定要有初始值。 //等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。 //此时程序在此发生阻塞 char sendBuf[100]; sprintf(sendBuf,"Welcome %s to www.msn.com.cn",inet_ntoa(addrClient.sin_addr)); //用返回的套接字和客户端进行通信(send/recv)。 send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]; recv(sockConn,recvBuf,100,0); printf("%s\n",recvBuf); closesocket(sockConn);//关闭套接字。等待另一个用户请求 } }
客户端
- 加载套接字库
- 创建套接字
- 向服务器发出连接请求
- 和服务器进行通信(send/recv)
- 关闭套接字
#include <Winsock2.h> #include <stdio.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData );//加载套接字库 if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);//创建套接字(socket)。 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//向服务器发出连接请求(connect)。 char recvBuf[100];//和服务器端进行通信(send/recv)。 recv(sockClient,recvBuf,100,0); printf("%s\n",recvBuf); send(sockClient,"This is blues_j",strlen("This is blues_j")+1,0); closesocket(sockClient);//关闭套接字。 WSACleanup();//必须调用这个函数清除参数 }
基于C#的Socket编程
服务端
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;using System.Net;namespace socket_server{ class Program { static IPAddress[] ServerIp; static int port = 6000; static void Main(string[] args) { // 基于TCP的Stream Scoket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 绑定端口 ServerIp = Dns.GetHostAddresses(""); socket.Bind(new IPEndPoint(ServerIp[2], port)); // 开始监听,设定最大队列长度 socket.Listen(4); // 接受客户端连接请求 socket.BeginAccept(new AsyncCallback((ar) => { var client = socket.EndAccept(ar); client.Send(Encoding.Unicode.GetBytes("Accept your request at " + DateTime.Now.ToString())); //定时器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) => { //检测客户端连接状态 if (client.Connected) { try { //Console.WriteLine("Heart Beat " + DateTime.Now.ToString()); ; } catch (SocketException ex) { Console.WriteLine(ex.Message); } } else { timer.Stop(); timer.Enabled = false; Console.WriteLine("Client is disconnectd"); } }; timer.Start(); //接收客户端消息 client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client); }), null); Console.WriteLine("[" + ServerIp[2].ToString() + ":" + port.ToString() + "]" + "Server is ready!"); Console.Read(); } static byte[] buffer = new byte[1024]; public static void ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; var length = socket.EndReceive(ar); //var message = Encoding.Unicode.GetString(buffer, 0, length); var message = Encoding.UTF8.GetString(buffer, 0, length); Console.WriteLine("[" + socket.RemoteEndPoint.ToString() + "]" + message); socket.Send(Encoding.UTF8.GetBytes("[" + ServerIp[2].ToString() + ":" + port.ToString() + "]" + "Hey this is a response from server " + DateTime.Now.ToString() + '\0')); socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch (Exception ex){ Console.WriteLine(ex.Message); } } }}
客户端
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;namespace SocketClient{ class Program { static void Main(string[] args) { //创建一个Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //连接到指定服务器的指定端口 socket.Connect("localhost", 6000); Console.WriteLine("connect to the server"); //实现接受消息的方法 socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); //接受用户输入,将消息发送给服务器端 while(true) { var message = "Message from client : " + Console.ReadLine(); var outputBuffer = Encoding.Unicode.GetBytes(message); socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null); } } static byte[] buffer = new byte[1024]; public static void ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; var length = socket.EndReceive(ar); //读取出来消息内容 var message = Encoding.Unicode.GetString(buffer, 0, length); //显示消息 Console.WriteLine(message); //递归接收下一个消息 socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch(Exception ex) { Console.WriteLine(ex.Message); } } }
阅读全文
0 0
- socket编程--socket基本概念
- socket编程--socket基本概念
- socket编程
- socket编程
- Socket 编程
- socket编程
- Socket编程
- Socket编程
- Socket编程
- Socket编程
- SOCKET编程
- socket编程
- Socket编程
- socket编程
- Socket 编程
- Socket 编程
- socket 编程
- socket编程
- 图解HTTP(七)
- struts2基本配置详解
- Java中的equals和==
- 解决APP启动时都会出现一会的空白页
- Spring Boot应用程序启动器
- Socket 编程
- 如何减少PHP-FPM的内存占用
- ######【spring属性注入(Ioc的DI)总结】:注解方式属性注入,属性名任意.=for理解:Aop注入代理对象时,注入被增强类对象时,属性名为proxy(自定义)。
- 数量金融学(8):Markowitz均值-方差模型(2)
- 88. Merge Sorted Array
- Java时间日期格式转换
- Python3 操作系统与路径 模块(os / os.path / pathlib)
- shell-1
- Python实现定时任务