C\#윈도 서비스 기반 채 팅 프로그램(1)

본 고 는 C\#를 통 해 윈도 서 비 스 를 개발 하고 배치 하 는 방법 을 보 여 줍 니 다.이 서 비 스 는 각 클 라 이언 트 의 정보 통신 을 제공 하여 랜 에 적용 합 니 다.TCP 프로 토 콜 을 사용 하여 단일 서버 연결 모드 가 한 쌍 이상 입 니 다.여러 대의 서버 의 경우 클 라 이언 트 연결 수가 미리 설 정 된 값 을 초과 할 때 자동 으로 부하 전 이 를 할 수 있 고 물론 수 동 으로 서버 를 전환 할 수 있 으 며 이런 장면 은 실제 프로젝트 에서 광범 위 하 게 응용 된다.
간단 한 메 시 지 는 서버 를 통 해 전달 되 고 파일 류 의 메 시 지 는 클 라 이언 트 가 스스로 연결 을 만들어 전송 합 니 다.후속 기능 은 천천히 완 선 될 것 이다.
사용자 정의 프로 토 콜:

1.새 Windows 서비스 항목

2.프로필 수정 추가

<appSettings>
  <add key="maxQueueCount" value="10"/>
  <add key="failoverServer" value="192.168.250.113,192.168.250.141"/>
</appSettings>
설명:max QueueCount 는 최대 연결 수 이 며,failoverServer 고장 으로 예비 서버(여러 서버,분리)를 옮 깁 니 다.
3.ChatService 오른쪽 단 추 를 누 르 면 설치 프로그램 이 추 가 됩 니 다.이 때 ProjectInstaller.cs 파일 이 자동 으로 추 가 됩 니 다.파일 에 기본적으로 serviceProcessInstaller 1 과 serviceInstaller 1 두 구성 요 소 를 추가 합 니 다.

serviceInstaller 1 과 serviceProcessInstaller 1 의 속성 정 보 를 수정 합 니 다.그림 참조


StartType 속성 설명:
Automatic 지시 서 비 스 는 시스템 이 시 작 될 때(또는 이미)운영 체제 에서 시 작 됩 니 다.자동 으로 시작 되 는 서비스 가 수 동 으로 시작 되 는 서비스 에 의존 하면 수 동 으로 시작 되 는 서비스 도 시스템 이 시 작 될 때 자동 으로 시 작 됩 니 다.
Disabled 는 사용자 나 프로그램 에서 시작 할 수 없 도록 이 서 비 스 를 사용 하지 않 으 라 고 지시 합 니 다.
Manual 지시 서 비 스 는 사용자("서비스 제어 관리자"사용)나 응용 프로그램 에서 만 수 동 으로 시 작 됩 니 다.
계 정 속성 설명:
  LocalService    로 컬 컴퓨터 의 비 특권 사용자 계 정 으로 이 계 정 은 익명 의 증 거 를 모든 원 격 서버 에 제공 합 니 다.
  LocalSystem    서비스 제어 관리자 가 사용 하 는 계 정 은 로 컬 컴퓨터 의 많은 권한 을 가지 고 네트워크 의 컴퓨터 로 사용 된다.
  NetworkService    광범 위 한 로 컬 특권 을 가 진 계 정 을 제공 합 니 다.이 계 정 은 컴퓨터 의 증 거 를 모든 원 격 서버 에 제공 합 니 다.
  User    네트워크 상에 서 특정한 사용자 가 정의 하 는 계 정.ServiceProcessInstaller.Account 구성원 에 게 user 를 지정 하면 시스템 이 서 비 스 를 설치 할 때 올 바른 사용자 이름과 비밀 번 호 를 입력 하 는 것 을 알려 줍 니 다.ServiceProcessInstaller 인 스 턴 스 의 Username 과 Password 라 는 두 속성 설정 값 을 입력 하지 않 는 한.
4.완료 후 ChatService 코드 를 열 고 OnStart 와 OnStop 방법(즉,서비스의 시작 과 정지 방법)을 다시 씁 니 다.다른 방법 을 다시 쓰 려 면 ServiceBase 에서 보십시오.
5.프로젝트 에 서비스 등록 과 스 크 립 트 파일 마 운 트 해제 추가

Install.bat
@echo off
path %SystemRoot%\Microsoft.NET\Framework\v4.0.30319;%path%
installutil %~dp0\WindowsChat.exe
%SystemRoot%\system32\sc failure "ChatService" reset= 30 actions= restart/1000
pause
@echo on

Uninstall.bat
@echo off
path %SystemRoot%\Microsoft.NET\Framework\v4.0.30319;%path%
installutil -u %~dp0\WindowsChat.exe
pause
@echo on

설명:%~dp0 은 bat 파일 이 있 는 디 렉 터 리 를 표시 합 니 다.
파일 속성 선택 시종 복사-내용,그래 야 출력 폴 더 에 생 성 됩 니 다.

6.위 에 있 는 OnStart 와 OnStop 재 작성 방법 으로 돌아 가기
SocketHelper 클래스 만 들 기

namespace WindowsChat
{
  public delegate void WriteInfo(string info);

  public class SocketHelper
  {
    #region     
    public SocketHelper()
    {
    }
    public SocketHelper(WriteInfo method)
    {
      this.method = method;
    }
    #endregion

    public static Socket LocalSocket = null;
    private object lockObj = new object();
    public static List<Socket> Clients = new List<Socket>();
    private WriteInfo method = null;

    /// <summary>
    ///   Socket
    /// </summary>
    /// <param name="port">     11011</param>
    /// <param name="backlog">The maximum length of the pending connections queue.</param>
    /// <returns></returns>
    public Socket Create(int port = 11011, int backlog = 100)
    {
      if (LocalSocket == null)
      {
        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);//      IP   
        LocalSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        LocalSocket.Bind(ipEndPoint);
        LocalSocket.Listen(backlog);
      }
      return LocalSocket;
    }

    /// <summary>
    ///        
    /// </summary>
    /// <param name="id">  </param>
    /// <returns></returns>
    private Socket FindLinked(string id)
    {
      foreach (var item in Clients)
      {
        if (item.RemoteEndPoint.ToString() == id)
          return item;
      }
      return null;
    }

    /// <summary>
    ///       
    /// </summary>
    public void Accept()
    {
      if (LocalSocket != null)
      {
        while (true)
        {
          Socket client = LocalSocket.Accept();
          Thread thread = new Thread(new ParameterizedThreadStart(Revice));
          thread.Start(client);
          WriteLog("   :" + client.RemoteEndPoint.ToString() + "   ");
          lock (lockObj)
          {
            Clients.Add(client);
          }
          BroadCast("ADD|" + client.RemoteEndPoint.ToString());
        }
      }
    }

    /// <summary>
    ///   
    /// </summary>
    /// <param name="info">  </param>
    private void WriteLog(string info)
    {
      using (FileStream fs = new FileStream("C:\\chatservice.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
      {
        using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
        {
          sw.WriteLine(info);
        }
      }
      if (method != null)
      {
        method(info);
      }
    }

    /// <summary>
    ///   
    /// </summary>
    /// <param name="info">  </param>
    public void BroadCast(string info)
    {
      foreach (var item in Clients)
      {
        try
        {
          item.Send(Encoding.UTF8.GetBytes(info));
        }
        catch (Exception ex)
        {
          WriteLog(item.RemoteEndPoint.ToString() + ex.Message);
          continue;
        }
      }
    }

    /// <summary>
    ///     
    /// </summary>
    /// <param name="client"></param>
    public void Revice(object client)
    {
      Socket param = client as Socket;
      var remoteName = param.RemoteEndPoint.ToString();
      if (param != null)
      {
        int res = 0;
        while (true)
        {
          byte[] buffer = new byte[10240];
          int size = param.ReceiveBufferSize;
          try
          {
            res = param.Receive(buffer);
          }
          catch (SocketException ex)
          {
            if (ex.SocketErrorCode == SocketError.ConnectionReset)
            {
              Clients.Remove(param);
              WriteLog("   :" + remoteName + "    1");
              BroadCast("REMOVE|" + remoteName);
              param.Close();
              return;
            }
          }

          if (res == 0)
          {
            Clients.Remove(param);
            WriteLog("   :" + remoteName + "    2");
            BroadCast("REMOVE|" + remoteName);
            param.Close();
            return;
          }
          var clientMsg = Encoding.UTF8.GetString(buffer, 0, res);
          WriteLog(string.Format("     {0}  :{1}", remoteName, clientMsg));
          if (clientMsg == "GETALL")
          {
            StringBuilder sb = new StringBuilder();
            foreach (var item in Clients)
            {
              sb.AppendFormat("{0}|", item.RemoteEndPoint.ToString());
            }
            param.Send(Encoding.UTF8.GetBytes("ALL|" + sb.ToString()));
          }
          else if (clientMsg == "OFFLINE")
          {
            if (Clients.Contains(param))
            {
              Clients.Remove(param);
              WriteLog("   :" + remoteName + "    2");
              BroadCast("REMOVE|" + remoteName);
              param.Close();
              return;
            }
          }
          else if (clientMsg.StartsWith("TRANST|"))
          {
            var msgs = clientMsg.Split('|');
            var toSocket = FindLinked(msgs[1]);
            if (toSocket != null)
            {
              WriteLog(remoteName + "  " + msgs[1] + "   " + msgs[2]);
              toSocket.Send(Encoding.UTF8.GetBytes("TRANSF|" + remoteName + "|" + msgs[2]));
            }
          }
        }
      }
    }
  }
}
OnStart 와 OnStop 재 작성 방법

public partial class ChatService : ServiceBase
{
    SocketHelper helper;
    Thread mainThread;

    public ChatService()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      if (helper == null)
      {
        helper = new SocketHelper();
      }
      helper.Create();
      mainThread = new Thread(new ThreadStart(helper.Accept));
      mainThread.IsBackground = true;
      mainThread.Start();
    }

    protected override void OnStop()
    {
      helper.BroadCast("SHUTDOWN");
    }
}

이로써 간단 하고 쉬 운 윈도 서비스의 채 팅 서버 개발 이 완료 되 었 고 후속 적 으로 이 를 바탕 으로 확 대 될 것 이다.
install.bat 실행(관리자 로 실행)그림 참조

7.services.msc 를 실행 하여 ChatService 서 비 스 를 찾 을 수 있 습 니 다.정상적으로 작 동 정지 설명 배치 성공!

물론 실행 파일 이 있 는 디 렉 터 리 에 InstallUtil.exe 를 복사 할 수도 있 습 니 다.예 를 들 어 c:\bin\
배포 스 크 립 트
  cd c:\bin\
  InstallUtil WindowsChat.exe
스 크 립 트 마 운 트 해제
  InstallUtil -u WindowsChat.exe
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기