socket協議介紹

  本文主要講述了Socket協議腳本的基礎知識和編寫方法,讓你們可以在短期內快速掌握簡單的Socket協議腳本的編寫方法。
  
  1.socket協議介紹
  
  Socket協議有萬能協議之稱,不少系統底層都是用的socket協議,用處十分普遍。
  
  1.1 Socket通信方式說明
  
  與socket通信有兩種方式,一種是創建長鏈接,創建後不停的發送,接收;另外一種是創建短鏈接,即創建鏈接發送報文,接收報文關閉鏈接
  
  1.2 Socket協議發送的buf類型介紹
  
  Send buffer類型分爲字符串和xml類型
  
  1.3 Socket協議腳本編寫前提:
  
  與項目組溝通,確認是不是socket協議,由項目組提供服務器IP和端口號還有socket協議交易的報文發送及接收報文對,及交易接口文檔,瞭解清楚報文的數據長度,參數化字段,結構,表明什麼等,瞭解清楚後進行socket協議腳本的開發。
  
  1.四、Socket協議腳本函數說明及實例:
  
  1)名稱 lrs_create_socket();
  
  建立socket鏈接,添加IP和端口號,若是建立成功返回值爲0,反之則返回爲非0數值。(對於長鏈接,創建socket鏈接放在vuser_init函數中,短鏈接放在Action中便可) 實例: lrs_create_socket("socket0","TCP","RemoteHost=180.170.150.230:7700",  LrsLastArg);
  
  2)名稱 lrs_send();
  
  發送socket請求消息,取緩衝區buf0的報文併發送。
  
  實例: lrs_send("socket0","buf1",LrsLastArg);
  
  3)名稱 lrs_receive();
  
  接收socket的響應報文,放置buf1中。
  
  實例:lrs_receive("socket0","buf2",LrsLastArg);
  
  4)名稱 lrs_get_last_received_buffer();
  
  獲取最後收到的buffer和大小,其中將最後收到的buffer的值賦給RecvBuf變量,將大小賦值給RecvLen。
  
  實例:   lrs_get_last_received_buffer("socket0",&recvBuf,&recvLen);
  
  5)名稱 lrs_free_buffer();
  
  爲防止內存泄露,釋放內存空間。
  
  實例:  lrs_free_buffer(recvBuf);
  
  6)名稱 lrs_close_socket();
  
  關閉Socket鏈接,(對於長鏈接,關閉socket鏈接應放在vuser_end函數中)
  
  實例:  lrs_close_socket("socket0");
  
  其餘經常使用的Socket函數:
  
  lrs_set_send_buffer("socket0", sSendPkg, iLenOfPkg );//指定要發送的socket信息
  
  lrs_get_buffer_by_name("buf0", sSendPkg, iLenOfPkg);// 獲取收到的buffer和大小
  
  lrs_length_send("socket0","buf0",1,"Size=4","Encoding=1",LrsLastArg);
  
  關聯函數:
  
  lrs_save_param_ex("socket0","received","",151,7,"ascii","response");//取指定位置字符串保存到變量,以便判斷事務是否成功
  
  lrs_save_searched_string();//在指定位置搜索字符串,將出現的字符串報錯到參數中
  
  超時函數
  
  lrs_set_connect_timeout();//設置鏈接超時時間
  
  lrs_set_recv_timeout();//設置服務器響應超時時間
  
  lrs_set_recv_timeout2();//設置接收超時時間,使系統不去檢查回收的內容是否一致
  
  二、Socket腳本編寫
  
  2.1 簡單劃分步驟
  
  這種方法是我無心在一片文章中看到的,整體說來,比較簡單。就像把大象放進冰箱同樣,總共分三步:
  
  第一步:把冰箱門打開
  
  //創建到服務端的鏈接
  
  rc =    lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=128.64.64.23:8988", LrsLastArg);
  
  if (rc==0)
  
  lr_output_message("Socket  was successfully created ");
  
  else
  
  lr_output_message("An error occurred while creating the socket, Error Code: %d", rc);
  
  第二步:把大象裝進去
  
  lrs_send("socket0", "buf0", LrsLastArg);   //往"socket0"發送"buf0"中的數據
  
  lrs_receive("socket0", "buf1", LrsLastArg);//將"socke0"中返回的數據存放到"buf1"中
  
  第三步:把冰箱門帶上
  
  //關閉鏈接
  
  lrs_close_socket("socket0");
  
  2.2 詳細劃分步驟
  
  ◇變量的聲明與定義
  
  ◇ 建立socket鏈接
  
  ◇ 發送socket請求
  
  ◇ 接收socket響應
  
  ◇ 從返回Buffer 中抽取結果
  
  ◇ 結果判斷
  
  ◇ 釋放內存
  
  ◇ 斷開鏈接。
  
  2.3 實例腳本
  
  下面咱們就是用一個實際項目不一樣報文格式的腳本進行講解;
  
  若項目是短鏈接,且報文不是從文件中讀取信息時,vuser_init和vuser_end部分默認便可,主要在Action中開發測試腳本和在data.ws中傳輸數據到Action的代碼中。
  
  Vuser_init.c
  
  #include   "lrs.h"
  
  vuser_init()
  
  {
  
  lrs_startup(257);
  
  return 0;
  
  }
  
  Action.c
  
  #include "lrs.h"
  
  Action()
  
  {
  
  int rc,rv;//保存鏈接成功返回值
  
  char *recvBuf;//保存接收數據的內容
  
  int recvLen;//保存接收數據的大小
  
  /*對於長鏈接,創建socket鏈接放在vuser_init函數中,短鏈接放在Action中便可*/
  
  rc=lrs_create_socket("socket0","TCP","RemoteHost=IP:端口",  LrsLastArg);
  
  //判斷鏈接是否建立成功
  
  if(rc==0){
  
  lr_output_message("Socket鏈接建立成功");
  
  }
  
  else{
  
  lr_error_message("Socket鏈接建立失敗!錯誤碼=%d",rc);
  
  return -1;
  
  }
  
  lr_start_transaction("XXXX_1234_FCX");//事務開始
  
  //發送socket請求消息(數據包內容放在data.ws中)
  
  lrs_send("socket0", "buf0", LrsLastArg); //取緩衝區buf0的報文併發送
  
  rv = lrs_receive("socket0", "buf1", LrsLastArg);//接收響應報文
  
  if(rv==0){
  
  lr_output_message("Socket接收返回消息成功");
  
  }
  
  else{
  
  lr_error_message("Socket接收返回消息失敗!錯誤碼=%d",rv);
  
  return -1;
  
  }
  
  //獲取最後收到的buffer和大小
  
  lrs_get_last_received_buffer("socket0",&recvBuf,&recvLen);
  
  /*設置檢查點,驗證返回數據是否成功,這個根據各交易具體狀況進行判斷,如下示例是經過返回報文的長度大於3即爲成功*/
  
  if(recvLen>3){
  
  lr_end_transaction("XXXX_1234_FCX ",PASS);
  
  }
  
  else{
  
  lr_end_transaction("XXXX_1234_FCX ",FAIL);
  
  lr_error_message("XXXX_8550_FCX Fail!出錯信息:[%s]", recvBuf);//交易失敗時,輸出RecvBuf返回信息,用於排查出錯緣由
  
  }
  
  lrs_free_buffer(recvBuf); //釋放recvBuf內存空間,不然會引發內存泄露
  
  /*關閉Socket鏈接,對於長鏈接,關閉socket鏈接應放在vuser_end函數中*/
  
  lrs_close_socket("socket0");
  
  return 0;
  
  AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(JobService.class);
  
  for (String beanname:context.getBeanDefinitionNames())
  
  {
  
  System.out.println("--------"+beanname);
  
  }
  
  System.out.println("context.getBean(JobService.class) = " + context.getBean(JobService.class));
  
  複製代碼
  
  這點代碼很簡單  初始化bean,而後再來拿bean,咱們點進AnnotationConfigApplicationContext來看
  
  複製代碼
  
  public AnnotationConfigApplicationContext(Class<?>... annotatedClasses)
  
  {
  
  this();
  
  register(annotatedClasses);
  
  refresh();
  
  }
  
  複製代碼
  
  進⼊以後 會調用 this()默認無參構造方法
  
  public AnnotationConfigApplicationContext() {
  
  this.reader = new AnnotatedBeanDefinitionReader(this);
  
  this.scanner = new www.tianjiuyule178.com  ClassPathBeanDefinitionScanner(this);
  
  }
  
  調⽤這個⽆參構造⽅法的同時 他會調用⽗類的構造方法,在調用父類構造⽅方法時 他new了一個對象
  
  public GenericApplicationContext() {
  
  this.beanFactory = new DefaultListableBeanFactory();
  
  }
  
  也就是 DefaultListableBeanFactory,固然 這個就是所謂咱們日常所說的 bean工廠,其父類就是 BeanFactory,BeanFactory有不少子類,DefaultListableBeanFactory就是其中一個⼦類。 那麼 bean的⽣命週期是圍繞那個⽅法呢,就是refresh()⽅法。也就是bean的整個生命週期是圍繞refresh() 來進行的
  
  在refresh()咱們能夠看到
  
  複製代碼
  
  public void refresh() throws BeansException, IllegalStateException {
  
  synchronized (this.startupShutdownMonitor)www.dayuzaixianyL.cn {
  
  // 準備好刷新上下文.
  
  prepareRefresh();
  
  // 返回一個Factory 爲何須要返回一個工廠  由於要對工廠進行初始化
  
  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  
  // 準備bean工廠,以便在此上下文中使用。
  
  prepareBeanFactory(beanFactory);
  
  try {
  
  // 容許在上下文子類中對bean工廠進行後處理。 在spring5  並未對此接口進行實現
  
  postProcessBeanFactory(beanFactory);
  
  // 在spring的環境中去執行已經被註冊的 Factory processors
  
  //設置執行自定義的postProcessBeanFactory和spring內部本身定義的
  
  invokeBeanFactoryPostProcessors(beanFactory);
  
  // 註冊postProcessor
  
  registerBeanPostProcessors(beanFactory);
  
  // 初始化此上下文的消息源。
  
  initMessageSource();
  
  // 初始化此上下文的事件多播程序。
  
  initApplicationEventMulticaster();
  
  // 在特定上下文子類中初始化其餘特殊bean。
  
  onRefresh();
  
  //檢查偵聽器bean並註冊它們。
  
  registerListeners();
  
  // 實例化全部剩餘的(非懶加載)單例。
  
  //new 單例對象
  
  finishBeanFactoryInitialization(beanFactory);
  
  // 最後一步:發佈相應的事件
  
  finishRefresh();
  
  }
  
  catch (BeansException ex) {
  
  if (logger.isWarnEnabled()) {
  
  logger.warn("Exception encountered during context initialization - " +
  
  "cancelling refresh attempt: " + ex);
  
  }
  
  // Destroy already created singletons to avoid dangling resources.
  
  destroyBeans(www.hnxinhe.cn);
  
  // Reset 'active' flag.
  
  cancelRefresh(ex);
  
  // Propagate exception to caller.
  
  throw ex;
  
  }
  
  finally {
  
  // Reset common introspection caches in Spring's core, since we
  
  // might not ever need metadata for singleton beans anymore...
  
  resetCommonCaches();
  
  }
  
  }
  
  }
  
  複製代碼
  
  那麼這裏面最重要就是finishBeanFactoryInitialization(beanFactory);這個方法就是描述 spring的一個bean如何初始化
  
  複製代碼
  
  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  
  // Initialize conversion service for this context.
  
  if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
  
  beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
  
  beanFactory.setConversionService(
  
  beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
  
  }
  
  // Register a default embedded value resolver if no bean post-processor
  
  // (such as a PropertyPlaceholderConfigurer bean) registered any before:
  
  // at this point, primarily for resolution in annotation attribute values.
  
  if (!beanFactory.hasEmbeddedValueResolver(www.yunyouuyL.com)) {
  
  beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment(www.chenghgongs.com).resolvePlaceholders(strVal));
  
  }
  
  // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
  
  String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  
  for (String weaverAwareName : weaverAwareNames) {
  
  getBean(weaverAwareName);
  
  }
  
  // Stop using the temporary ClassLoader for type matching.
  
  beanFactory.setTempClassLoader(null);
  
  // Allow for caching all bean definition metadata, not expecting further changes.
  
  beanFactory.freezeConfiguration();
  
  // 實例化全部單例對象
  
  beanFactory.preInstantiateSingletons();
  
  }
  
  複製代碼
  
  能夠看到前面是一些判斷 最重要的就是最後一個方法 beanFactory.preInstantiateSingletons();咱們看下preInstantiateSingletons()方法,它是ConfigurableListableBeanFactory這個接口的一個方法 咱們直接來看這個接口的實現 是由DefaultListableBeanFactory這個類 來實現
  
  複製代碼
  
  @Override
  
  public void preInstantiateSingletons() throws BeansException {
  
  if (logger.isDebugEnabled()) {
  
  logger.debug("Pre-instantiating singletons in www.baihuiyulegw.com " + this);
  
  }
  
  // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  
  // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  
  //全部bean的名字
  
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  
  // Trigger initialization of all non-lazy singleton beans...
  
  for (String beanName : beanNames) {
  
  RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  
  if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  
  if (isFactoryBean(beanName)) {
  
  Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
  
  if (bean instanceof FactoryBean) {
  
  final FactoryBean<?> factory = (FactoryBean<?>) bean;
  
  boolean isEagerInit;
  
  if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  
  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
  
  ((SmartFactoryBean<www.tianscpt.com>) factory)::isEagerInit,
  
  getAccessControlContext());
  
  }
  
  else {
  
  isEagerInit = (factory instanceof SmartFactoryBean &&
  
  ((SmartFactoryBean<?>) factory).isEagerInit());
  
  }
  
  if (isEagerInit) {
  
  getBean(beanName);
  
  }
  
  }
  
  }
  
  else {
  
  getBean(beanName);
  
  data.ws
  
  1)XML報文格式
  
  ;WSRData 2 1
  
  send  buf0 360
  
  "<?xmlversion=\"1.0\"encoding=\"GBK\"?>"
  
  "<TRANINFO>"
  
  "<HEAD>"
  
  "<TransCode>S001</TransCode>"
  
  "<TransDate>20170613</TransDate>"
  
  "<TransTime>144206</TransTime>"
  
  "<TransNo>21219603</TransNo>"
  
  "<Operator>999088</Operator>"
  
  "<TransInst>70090</TransInst>"
  
  "</HEAD>"
  
  "<MSG>"
  
  "<CustomerID><userID></CustomerID>"//客戶編號
  
  "<Type>3</Type>"//查詢類型
  
  "<BusinessType>01</BusinessType>"//業務類型
  
  "</MSG>"
  
  "</TRANINFO>"
  
  recv buf1 300
  
  -1
  
  2)16進制報文格式
  
  ;WSRData 2 1
  
  send  buf0 32
  
  "\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  
  " "
  
  "\x00\x00\x00\x00"
  
  "PID <tran>"
  
  recv  buf1 197
  
  "\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  
  "\x1e\x00\x00\x00\x00"
  
  "STW -1"
  
  "\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  
  "\x1e\x00\x00\x00\x00"
  
  "STT "
  
  "\x1f"
  
  -1
  
  其中buf0表明發送的報文的名稱,後跟的數字代碼發送報文長度,其下放置發送報文;buf1表明接收報文的名稱,後跟數字表明接收報文長度,其下放置接收報文。
  
  注意:該協議腳本參數化格式爲:<參數名>spring

相關文章
相關標籤/搜索