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

服务端

  1. 加载套接字(socket)库
  2. 创建套接字
  3. 绑定套接字到本地地址和端口
  4. 将套接字设为监听模式
  5. 等待客户请求到来,当请求到来后接受并返回此次连接的套接字
  6. 使用上一步的套接字和客户端通信(send/recv)
  7. 关闭套接字
#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);//关闭套接字。等待另一个用户请求     } }

客户端

  1. 加载套接字库
  2. 创建套接字
  3. 向服务器发出连接请求
  4. 和服务器进行通信(send/recv)
  5. 关闭套接字
#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);            }        }    }

原创粉丝点击