제가 서버를 하려고 하고있는데 크로스 쓰래드 문제가 생겨서 invoke를
해봤는데 이게 이제 연결은 되는데 문자가 떠야 될 부분들이 안뜨네요 ;;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net; // IPAddress
using System.Net.Sockets; //TcpListener 클래스사용
using System.Threading; //스레드 클래스 사용
using System.IO; //파일 클래스 사용
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
private TcpListener Server; //TCP 네트워크 클라이언트에서 연결 수신
private TcpClient SerClient; //TCP 네트워크 서비스에 대한 클라이언트 연결 제공
private NetworkStream myStream; //네트워크 스트림
private StreamReader myRead; //스트림 읽기
private StreamWriter myWrite; //스트림 쓰기
private Boolean Start = false; //서버 시작
private Boolean ClientCon = false; //클라이언트 시작
private int myPort; //포트
private string myName; //별칭(ID)
private Thread myReader, myServer; //스레드
private Boolean TextChange = false; //입력 컨트롤의 데이터입력 체크
private delegate void AddTextDele(string str);
private AddTextDele AddText;
public Form1()
{
InitializeComponent();
}
private void 설정ToolStripMenuItem_Click(object sender, EventArgs e)
{
this.설정ToolStripMenuItem.Enabled = false;//메뉴비활성화
this.plOption.Visible = true;//설정을 위한 상자 open
this.txtId.Focus();//id입력상자로 초점이동
}
private void btnSave_Click(object sender, EventArgs e)
{
ControlCheck();
}
private void ControlCheck()
{
if (this.txtId.Text == "")//ID가 입력되지 않았으면 ID입력
{
this.txtId.Focus();
}
else if (this.txtPort.Text == "")//PORT가 입력되지 않았으면 PORT입력
{
this.txtPort.Focus();
}
else
{
try
{
this.plOption.Visible = false;//설정이 완료되었으므로 설정상자를 비활성화
this.설정ToolStripMenuItem.Enabled = true;//상위메뉴바 활성화
this.tsbtnConn.Enabled = true;//연결메뉴 활성화
}
catch
{//에러메세지 박스 출력
MessageBox.Show("설정이 저장되지 않았습니다.", "에러", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void btnClose_Click(object sender, EventArgs e)
{
this.설정ToolStripMenuItem.Enabled = true; //설정 메뉴 활성화
this.plOption.Visible = false; //입력창 닫기
this.txtMessage.Focus();
}
private void tsbtnConn_Click(object sender, EventArgs e)
{
var addr = new IPAddress(0);//IPAddress 클래스의 개체를 초기화, 매개변수가 0->로컬단말의 아이피 가져옴
this.myName = this.txtId.Text;
this.myPort = Convert.ToInt32(this.txtPort.Text);
if (!(this.Start))//서버가 시작되지 않은 경우
{
try
{
Server = new TcpListener(addr, this.myPort);//ip주소와 포트번호를 인자로 TcpLIstener의 개체 생성
Server.Start();//Server 시작
this.Start = true;
this.txtMessage.Enabled = true;
this.btnSend.Enabled = true;
this.txtMessage.Focus();//메시지를 쓸 수 있도록 초점을 이동
this.tsbtnDisconn.Enabled = true;//연결을 끊을 수 있도록 메뉴 활성화
this.tsbtnConn.Enabled = false;//연결시도버튼 비활성화
//Thread클래스의 생성자를 이용하여 개체생성-> ServerStart()메서드로 클라이언트의 수신과 네트워크 스트림의 값을 수신하는 작업을 새로 생성한 스레스에서 수행
myServer = new Thread(ServerStart);
myServer.Start();
this.설정ToolStripMenuItem.Enabled = false;
}
catch
{
MessageView("서버를 실행할 수 없습니다.");
}
}
else
{
ServerStop(); //ServerStop() 함수 호출
}
}
private void MessageView(string strText)
{
this.rtbText.AppendText(strText + "\r\n");//입력한 텍스트와 엔터키추가
this.rtbText.Focus();//초점이동
this.rtbText.ScrollToCaret();// 컨트롤의 내용을 현재 캐럿 위치까지 스크롤
this.txtMessage.Focus();//초점이동
}
private void ServerStart()
{ //메세지출력
rtbText.Invoke(AddText, "서버 실행 : 챗 상대의 접속을 기다립니다...");
while (Start)//클라이언트가 접속될 때까지 기다림
{
try
{
SerClient = Server.AcceptTcpClient();//보류중인 연결요청을 받아들임
rtbText.Invoke(AddText, "챗 상대 접속..");
myStream = SerClient.GetStream();//데이터를 보내고 받는 데 사용한 NetworkStream을 반환하여 myStream 개체에 대입
myRead = new StreamReader(myStream);//읽기 스트림
myWrite = new StreamWriter(myStream);//저장 스트림
this.ClientCon = true;//클라이언트 연결 허용
myReader = new Thread(Receive);//스레드를 이용하여 myReader개체를 생성
myReader.Start();
}
catch { }
}
}
private void ServerStop() // 서버 모드 종료
{
this.Start = false;
this.txtMessage.Enabled = false;
this.txtMessage.Clear();
this.btnSend.Enabled = false;
this.tsbtnConn.Enabled = true;
this.tsbtnDisconn.Enabled = false;
this.ClientCon = false;
if (!(myRead == null))
{
myRead.Close(); //StreamReader 클래스 개체 리소스 해제
}
if (!(myWrite == null))
{
myWrite.Close(); //StreamWriter 클래스 개체 리소스 해제
}
if (!(myStream == null))
{
myStream.Close(); //NetworkStream 클래스 개체 리소스 해제
}
//복사2 붙여넣기
if (!(SerClient == null))
{
SerClient.Close(); //TcpClient 클래스 개체 리소스 해제
}
if (!(Server == null))
{
Server.Stop(); //TcpListen 클래스 개체 리소스 해제
}
if (!(myReader == null))
{
myReader.Abort(); //외부 스레드 종료
}
if (!(myServer == null))
{
myServer.Abort(); //외부 스레드 종료
}
if (!(AddText == null))
rtbText.Invoke(AddText, "연결이 끊어졌습니다.");
}
private void Receive()
{
try
{
while (this.ClientCon)//클라이언트의 연결이 종료될 때까지 계속 실행
{
if (myStream.CanRead)//스트림에서 데이터를 읽을 수 있는 경우
{
var msg = myRead.ReadLine();
var Smsg = msg.Split('&');//&를 기준으로 메시지 구분
if (Smsg[0] == "S001")//첫 구분자가 "S001“인 경우
{
this.tsslblTime.Text = Smsg[1];//상태바의 레이블에 날짜와 시간을 출력
}
else
{
if (msg.Length > 0) //읽은 메시지가 있는 경우
{
rtbText.Invoke(AddText, Smsg[0] + " : " + Smsg[1]);//MessageView()메서드를 이용화면에 출력
}
this.tsslblTime.Text = "마지막으로 받은 시각:" + Smsg[2];
}
}
}
}
catch { }
}
private void tsbtnDisconn_Click(object sender, EventArgs e)
{
try
{
if (this.SerClient.Connected)//연결중인 상태
{
var dt = Convert.ToString(DateTime.Now);
myWrite.WriteLine(this.myName + "&" + "채팅 APP가 종료되었습니다." + "&" + dt);
myWrite.Flush();
}
}
catch { }
ServerStop();//서버종료
this.설정ToolStripMenuItem.Enabled = true;
}
private void btnSend_Click(object sender, EventArgs e)
{
if (this.txtMessage.Text == "")
{
this.txtMessage.Focus();
}
else
{
Msg_send(); //Msg_send()함수 호출
}
}
private void Msg_send()
{
try
{
var dt = Convert.ToString(DateTime.Now);
//아이디 & 메시지 & 날짜시간을 보냄
myWrite.WriteLine(this.myName + "&" + this.txtMessage.Text + "&" + dt);
myWrite.Flush();
//서버의 rtbText(채팅창)에 id와 메시지 출력
MessageView(this.myName + ": " + this.txtMessage.Text);
this.txtMessage.Clear();
}
catch
{
rtbText.Invoke(AddText, "데이터를 보내는 동안 오류가 발생하였습니다.");
this.txtMessage.Clear();
}
}
private void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13) //엔터 키를 누를때
{
e.Handled = true; //소리 없앰
if (this.txtMessage.Text == "")
{
this.txtMessage.Focus();
}
else
{
Msg_send(); //Msg_send()함수 호출
}
}
}
private void txtMessage_TextChanged(object sender, EventArgs e)
{
//입력을 안하고 있던 상황에서 입력을 시작하는 경우
if (TextChange == false)
{
TextChange = true;//입력을 하고 있다고 지정
//정보전달의 암호: S001
myWrite.WriteLine("S001" + "&" + "상대방이 메시지 입력중입니다." + "&" + " ");
myWrite.Flush();
}
else if (this.txtMessage.Text == "" && TextChange == true)
{//메시지를 입력하지 않은 경우
TextChange = false;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ServerStop();//서버종료
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
교수님 강의 자료 보면서 따라하다가 크로스 쓰래드 문제가 생겨서 이렇게 햇는데 ;; 어디가 잘못된건지 못찾겠네요 ㅠㅠ
혹시 아시는 분들 계신가요 ?