SOCKET通信的基本步骤

   1)建立一个服务器ServerSocket,并同时定义好ServerSocket的监听端口;
   2)ServerSocket 调用accept()方法,使之处于阻塞。
   3)创建一个客户机Socket,并设置好服务器的IP和端口。
   4)客户机发出连接请求,建立连接。
   5)分别取得服务器和客户端ServerSocket 和Socket的InputStream和OutputStream.
   6)  利用Socket和ServerSocket进行数据通信。
/

在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:
同步:
      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。

例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事

异步:
      异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

例如 ajax请求(异步): 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

阻塞
     阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。

有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。 例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。

非阻塞
      非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
对象的阻塞模式和阻塞函数调用
对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。

1. 同步,就是我调用一个功能,该功能没有结束前,我死等结果。
2. 异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)
3. 阻塞,      就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
4. 非阻塞,  就是调用我(函数),我(函数)立即返回,通过select通知调用者

同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞!

阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回!

对于举个简单c/s 模式:

同步:提交请求->等待服务器处理->处理完毕返回这个期间客户端浏览器不能干任何事
异步:请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕
同步和异步都只针对于本机SOCKET而言的。

同步和异步,阻塞和非阻塞,有些混用,其实它们完全不是一回事,而且它们修饰的对象也不相同。
阻塞和非阻塞是指当进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪;

而同步和异步是指访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就绪与读写二个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待"通知")

//
客户端:
综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识,下面的程序段完整地实现了Web页面下载功能。用户只需在窗体上输入远程主机名(Dns 主机名或以点分隔的四部分表示法格式的 IP 地址)和预保存的本地文件名,并利用专门提供Http服务的80端口,就可以获取远程主机页面并保存在本地机指定文件中。如果保存格式是.htm格式,你就可以在Internet浏览器中打开该页面。适当添加代码,你甚至可以实现一个简单的浏览器程序。
  
  
  实现此功能的主要源代码如下:
  
  //"开始"按钮事件
  private void button1_Click(object sender, System.EventArgs e) 
{
   //取得预保存的文件名
   string fileName=textBox3.Text.Trim();
   //远程主机
   string hostName=textBox1.Text.Trim();
   //端口
   int port=Int32.Parse(textBox2.Text.Trim());
   //得到主机信息
   IPHostEntry ipInfo=Dns.GetHostByName(hostName);
   //取得IPAddress[]
   IPAddress[] ipAddr=ipInfo.AddressList;
   //得到ip
   IPAddress ip=ipAddr[0];
   //组合出远程终结点
   IPEndPoint hostEP=new IPEndPoint(ip,port);
   //创建Socket 实例
   Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
   try
   {
   //尝试连接
   socket.Connect(hostEP);
   }
   catch(Exception se)
   {
   MessageBox.Show("连接错误"+se.Message,"提示信息
   ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
  }
  //发送给远程主机的请求内容串
  string sendStr="GET / HTTP/1.1\r\nHost: " + hostName +
  "\r\nConnection: Close\r\n\r\n";
   //创建bytes字节数组以转换发送串
   byte[] bytesSendStr=new byte[1024];
   //将发送内容字符串转换成字节byte数组
   bytesSendStr=Encoding.ASCII.GetBytes(sendStr);
  try
  {
  //向主机发送请求
  socket.Send(bytesSendStr,bytesSendStr.Length,0);
  }
  catch(Exception ce)
   {
   MessageBox.Show("发送错误:"+ce.Message,"提示信息
   ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
   }
   //声明接收返回内容的字符串
   string recvStr="";
   //声明字节数组,一次接收数据的长度为1024字节
   byte[] recvBytes=new byte[1024];
   //返回实际接收内容的字节数
   int bytes=0;
  //循环读取,直到接收完所有数据
  while(true)
  {
   bytes=socket.Receive(recvBytes,recvBytes.Length,0);
   //读取完成后退出循环
   if(bytes<=0)
   break;
   //将读取的字节数转换为字符串
   recvStr+=Encoding.ASCII.GetString(recvBytes,0,bytes);
  }
  //将所读取的字符串转换为字节数组
  byte[] content=Encoding.ASCII.GetBytes(recvStr);
   try
   {
    //创建文件流对象实例
    FileStream fs=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
   //写入文件
   fs.Write(content,0,content.Length);
  }
  catch(Exception fe)
   {
    MessageBox.Show("文件创建/写入错误:"+fe.Message,"提示信息",MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
   }
    //禁用Socket
    socket.Shutdown(SocketShutdown.Both);
    //关闭Socket
    socket.Close();
   }
   }
//
/client端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace socketsample
{
 class Class1
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    c.Connect(ipe);
    string sendStr = "hello!This is a socket test";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    c.Send(bs, bs.Length, 0);
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = c.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    c.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}
//server端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Project1
{
 class Class2
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    s.Bind(ipe);
    s.Listen(0);
    Socket temp = s.Accept();
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    string sendStr = "Ok!Sucess!";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    temp.Send(bs, bs.Length, 0);
    temp.Shutdown(SocketShutdown.Both);
    temp.Close();
    s.Shutdown(SocketShutdown.Both);
    s.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}

SOCKET通信的基本步骤相关推荐

  1. Socket通信---网络通信学习笔记(一)

    两台计算机进行通信的基本前提: (1)IP地址: 每台计算机都有自己独一无二的IP地址,根据IP地址判断与哪台计算机进行通信. (2)端口号: 每个应用程序都有自己专属的端口,根据端口号判断与计算机中 ...

  2. 安卓Socket通信案例

    本案例是实现编写客户端负责发送内容.服务器端用来接收内容的程序. 1.编写服务器端程序(hello.java) 该程序是负责接收数据,需要单独编译运行.可以采用eclipse编译,编译之后将文件保存在 ...

  3. 1.Socket通信

    本博客部分内容参考教程来自C语言中文网. 进入socket通信首先要了解两个概念,第一:服务器端,第二:客户端.(区别是两者的服务对象不同.服务器端是为客户端服务的,客户端就是为真正的"客户 ...

  4. protobuf和socket通信简单实例

    protobuf和socket通信简单实例   protobuf是 Google 公司内部的混合语言数据标准,可以用来定义通信的协议,由于其有序列化和反序列化的操作,减小了存储或通信的数据量,从而达到 ...

  5. python udp创建addr_python高级:8.socket通信part1

    0.前言 如果可以的话,请先关注(专栏和账号),然后点赞和收藏,最后学习和进步.你的支持是我继续写下去的最大动力,个人定当倾囊而送,不负众望.谢谢!!! 1.前提 基于win10专业版64位系统+64 ...

  6. java socket通信

    socket通信是指两台计算机的两个程序之间的通信,双向链路的每一端都称为一个socket,但分为客户机和服务器. java.net提供了ServerSocket和Socket类,分别用于服务器和客户 ...

  7. Android网络编程的Socket通信总结

    创建服务器端的步骤: 1,指定端口实例化一个ServerSocket 2,调用ServerSocket的accept方法等待连接期间阻塞 3,获取位于底层的Socket流进行读写操作 4,将数据封装成 ...

  8. 操作系统实验报告9:进程间通信—管道和 socket 通信

    操作系统实验报告9 实验内容 实验内容:进程间通信-管道和 socket 通信. 编译运行课件 Lecture11 例程代码: alg.11-3-socket-input-2.c alg.11-4-s ...

  9. java与c 通信_Java与C之间的socket通信

    最近正在开发一个基于指纹的音乐检索应用,算法部分已经完成,所以尝试做一个Android App.Android与服务器通信通常采用HTTP通信方式和Socket通信方式.由于对web服务器编程了解较少 ...

最新文章

  1. 皇牌空战无限服务器,《皇牌空战:无限》正式停服 一个搏击长空的时代终结[多图]...
  2. 【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)
  3. Data Lake Analytics-数据分析时代迎来新变革
  4. Ajax+SpringMVC+JSON登录验证
  5. 谷歌移动UI框架Flutter入门
  6. Elastic控制查询精准度-minimum_should_match
  7. 九宫格摆法_九宫格照片墙摆法,9张照片墙6竖3横怎么摆?
  8. ssm 支付宝支付整合
  9. html古风颜色代码,数字报纸HTML版本
  10. 激光SLAM:激光雷达运动畸变补偿--轮速里程计辅助方法
  11. 2023年湖北省建筑类初级职称助理工程师电子版证书申报查询
  12. 利率市场化冲击传统资产负债管理 金融壹账通助力银行科技转型
  13. 【雷达原理】FMCW雷达简介
  14. 买笔记本的13个验机步骤
  15. RedisCommandExecutionException: ERR DISABLE You can‘t write or read against a disable instance
  16. 不要随意使用批量加QQ好友软件,不然你一定会后悔的!
  17. windows11怎么截屏
  18. 月球公转与自转(一)
  19. Mac打开所有分辨率的HiDPI
  20. 20230218英语学习

热门文章

  1. Git 分支管理-git stash 和git stash pop
  2. Object.keys() Object.values()
  3. 《流浪地球》 电影全集
  4. tr069相关协议说明
  5. USACO 06JAN 牛的舞会 洛谷2863
  6. 用户需求、己、竞争对手的关系
  7. easyUI 绑定右键菜单在数据行上显示
  8. SQL版DNN的安装心得
  9. Go编程技巧--io.Reader/Writer
  10. Vue2.0王者荣耀助手