다음 예제 프로그램은 간단한 소켓 통신을 구현하고 여러 클라이언트를 열 수 있습니다. 로컬 테스트는 통과했지만 온라인 테스트는 수행되지 않았습니다.
서버:
System.Net 사용,
System.Net.Sockets 사용,
System.Collections 사용
;
네임스페이스 MySocketServer1
{
공개 부분 클래스 Form1 : Form
{
개인 IPAddress serverIP = IPAddress.Parse("127.0.0.1");//개인 IPEndPoint serverFullAddr 테스트에 이 시스템을 사용하십시오
.//전체 터미널 주소
개인 소켓 양말
; Timer myTimer;
private ArrayList alSock;//여러 연결이 설정된 경우 연결을 저장하는 데 사용됩니다.
공개 Form1()
{
초기화구성요소()
}
;
private void btStart_Click(object sender, EventArgs e)
{
serverFullAddr = new IPEndPoint(serverIP, 1000); //포트 번호 1000을 가져옵니다.
//소켓 객체를 구성하고 소켓 유형은 "스트림 소켓"이며 5-튜플을 지정합니다. 프로토콜 요소
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
//5-튜플의 로컬 바이너리, 즉 로컬 호스트 주소 및 포트 번호를 지정합니다
.sock.Bind(serverFullAddr)
/ /Listen 들어오는 연결이 있는지 여부에 따라 보류 중인 연결 대기열의 최대값을 20으로 지정합니다.
sock.Listen(20);
alSock = 새로운 ArrayList();
//1초의 시간 간격으로 타이머를 구성합니다. 즉, 연결 요청 큐에서 대기 중인 첫 번째 연결 요청을 얻기 위해 매초 accept() 메서드를 실행합니다.
myTimer =new System.Timers.Timer(1000 )
; 경과 +=new System.Timers.ElapsedEventHandler(myTimer_Elapsed)
=
true
;
private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
//accept()를 실행하면 일시 중단 대기열이 비어 있으면 이 스레드가 차단되고 이전 문으로 인해 타이머가 중지됩니다.
, // 연결이소켓
에 전달될 때까지
acceptSock = sock.Accept();// accept()에 의해 생성된 소켓 객체를 ArrayList에 저장합니다.
alSock.Add(acceptSock)
// Threading.Timer 객체를 구성합니다. 그러면 프로그램이 다른 스레드를 시작하게 됩니다. 스레드는 콜백 함수를 실행하며 대리자 제한 //함수 매개 변수는 개체 유형이어야 합니다. Threading.Timer 생성자의 두 번째 매개변수는 콜백 함수에 전달되는 매개변수입니다. //세 번째 매개변수는 콜백 함수를 호출하기 전의 지연 시간을 지정합니다. 0이면 마지막 매개변수는 호출할 시간을 지정합니다. 콜백 함수 // 간격, 0으로 설정하면 한 번만 실행됩니다.
System.Threading.Timer ti = new System.Threading.Timer(new
TimerCallback(ReceiveMsg)
,acceptSock
, 0, 0);
private void receiveMsg(object obj)
{
Socket acceptSock = (Socket)obj;
try
{
while (true)
{
byte[] byteArray = new byte[100];
//데이터 수신
//바이트 변환 배열을
문자열로 strRec = System.Text.Encoding.UTF8.GetString(byteArray);
if (this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(this.ChangeRickTextBox), new
object[] { strRec , EventArgs.Empty });
}
}
}
catch(Exception ex)
{
acceptSock.Close();
MessageBox.Show("S:Receive Message Error"+ex.Message
)
;
private void ChangeRickTextBox(object obj,EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine)
}
private void btSend_Click(object sender, EventArgs e)
{
Socket sc=null;
byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray())
try
{
//다음에 여러 가지가 있습니다. 동시에 클라이언트가 연결되면 textBox1에 보낼 연결을 입력합니다.
int index = int.Parse(this.textBox1.Text.Trim())
sc = (Socket)alSock[index - 1];
//데이터sc
보내기
.Send(byteSend);
}
catch(Exception ex)
{
if(sc != null)
{
sc.Close()
}
MessageBox.Show
("S:메시지 보내기 오류"+ex.Message)
;
private void btClose_Click(object sender, EventArgs e)
{
try
{
Application.Exit()
}
catch (Exception ex)
{
MessageBox.Show("S:Close Socket Error" + ex.Message)
} }
}
}
==
= = == == == == == == == == == == == == == == == == == == == == == == == = = = = == == == ==
클라이언트:
System.Net 사용;
System.Net.Sockets 사용
;
네임스페이스 MySocketClient1
{
공개 부분 클래스 Form1 : Form
{
개인 IPAddress serverIP = IPAddress.Parse("127.0.0.1")
개인 IPEndPoint serverFullAddr
;
공개 Form1()
{
초기화구성요소()
}
;
private void btConnect_Click(개체 발신자, EventArgs e)
{
try
{
serverFullAddr = new IPEndPoint(serverIP, 1000);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
// 원격 호스트에 대한 연결 설정
//데이터를 수신하기 위해 새 스레드를 시작합니다.
Thread t = new Thread(new ThreadStart(ReceiveMsg));
t.Name = "Receive Message";
//스레드는 백그라운드 스레드이거나 포그라운드 스레드입니다. 백그라운드 스레드는 백그라운드 스레드가 // 프로세스 종료를 방지하지 않는다는 점을 제외하면 포그라운드 스레드와 유사합니다. 프로세스에 속한 모든 전경 스레드가 종료되면 공용 언어 런타임은 // 아직 활성 상태인 모든 배경 스레드에서 Abort를 호출하여 프로세스를 종료합니다.
t.IsBackground = true;
t.Start();
}
catch
(Exception ex)
{
MessageBox.Show(ex.Message)
}
private
void
receiveMsg()
{
try
{
while (true)
{
byte[] byteRec = new byte[100]
;
string strRec = System.Text.Encoding.UTF8.GetString(byteRec);
(this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(ChangeRtb), new object[]
{ strRec, EventArgs.Empty })
}
}
}
catch(Exception ex)
{
MessageBox.Show("수신 메시지 오류 "+ex.메시지);
}
}
private void ChangeRtb(object obj, EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine)
}
private void btSend_Click(object sender, EventArgs e)
{
byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray())
try
{
this.sock.Send(byteSend)
}
catch
{
MessageBox.Show("메시지 보내기 오류")
}
}
private void btClose_Click(object sender, EventArgs e)
{
try
{
this.sock.Shutdown(SocketShutdown.Receive);
this.sock.Close();
Application.Exit()
}
catch
{
MessageBox.Show("종료 오류") ;
} }
}
}
퍼즐
:
클라이언트 측에 빨간색으로 표시된 명령문: this.sock.Shutdown(SocketShutdown.Receive)(
this.sock.Shutdown(SocketShutdown.Both) 또는 this.sock.Shutdown(SocketShutdown. Send);
닫기 버튼을 클릭하면 CPU 사용량이 100%로 치솟습니다. 그러나 this.sock.Shutdown(SocketShutdown.Receive);을 사용하거나
Shutdown() 메서드를 호출하지 않으면 이 문제가 발생하지 않습니다. 클라이언트가 Shutdown()을 사용하면 안 되나요?
http://www.cnblogs.com/KissKnife/archive/2006/08/13/475707.html