안드로이드 소켓 프로그래밍 테스트를 위해 간단한 채팅프로그램을 만들어 봤습니다.
클라이언트는 자바를 이용해 만들었고 서버는 C#을 이용해 만들었습니다.
- 클라이언트 -
main.xml
-------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView
android:text="닉네임"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<EditText
android:text="Guest"
android:id="@+id/connText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
</EditText>
<Button
android:text=" 접속 "
android:id="@+id/connBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="connBtnClick">
</Button>
<Button
android:text=" 종료 "
android:id="@+id/closeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="connBtnClick">
</Button>
</LinearLayout>
<ScrollView
android:id="@+id/scrollView1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:fillViewport="true"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:id="@+id/text01"
android:singleLine="false"
android:layout_height="wrap_content"
/>
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:gravity="bottom">
<EditText
android:id="@+id/chatText"
android:text=""
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="1"
>
</EditText>
<Button
android:text="보내기"
android:id="@+id/sendBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="connBtnClick">
</Button>
</LinearLayout>
</LinearLayout>
-------------------------------------------------------------------------------------------
andChatSample.java
-------------------------------------------------------------------------------------------
package exam.andChatSample;
import java.io.*;
import java.net.*;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class andChatSample extends Activity {
/** Called when the activity is first created. */
public Socket cSocket = null;
private String server = "123.123.123.123"; // 서버 ip주소
private int port = 9000; // 포트번호
public PrintWriter streamOut = null;
public BufferedReader streamIn = null;
public chatThread cThread = null;
public TextView tv;
public EditText nickText;
public EditText msgText;
public ScrollView sv;
public String nickName;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sv = (ScrollView)findViewById(R.id.scrollView1);
tv = (TextView)findViewById(R.id.text01);
nickText = (EditText)findViewById(R.id.connText);
msgText = (EditText)findViewById(R.id.chatText);
logger("채팅을 시작합니다.");
}
public void onDestroy() { // 앱이 소멸되면
super.onDestroy();
if (cSocket != null) {
sendMessage("# [" + nickName + "]님이 나가셨습니다.");
}
}
public void connBtnClick(View v) {
switch (v.getId()) {
case R.id.connBtn: // 접속버튼
if (cSocket == null) {
nickName = nickText.getText().toString();
logger("접속중입니다...");
connect(server, port , nickName);
}
break;
case R.id.closeBtn: // 나가기 버튼
if (cSocket != null) {
sendMessage("# [" + nickName + "]님이 나가셨습니다.");
}
break;
case R.id.sendBtn: // 메세지 보내기 버튼
if (cSocket != null) {
String msgString = msgText.getText().toString();
if (msgString != null && !"".equals(msgString)) {
sendMessage("[" + nickName + "] " + msgString);
msgText.setText("");
}
} else {
logger("접속을 먼저 해주세요.");
}
break;
}
}
public void connect(String server, int port, String user) {
try {
cSocket = new Socket(server, port);
streamOut = new PrintWriter(cSocket.getOutputStream(), true); // 출력용 스트림
streamIn = new BufferedReader(new InputStreamReader(cSocket.getInputStream())); // 입력용 스트림
sendMessage("# 새로운 이용자[" + user + "]님이 들어왔습니다.");
cThread = new chatThread();
cThread.start();
}catch (Exception ex) {
logger("접속이 제대로 이루어 지지 않았습니다.");
}
}
private void logger(String MSG) {
tv.append(MSG + "\n"); // 텍스트뷰에 메세지를 더해줍니다.
sv.fullScroll(ScrollView.FOCUS_DOWN); // 스크롤뷰의 스크롤을 내려줍니다.
}
private void sendMessage(String MSG) {
try {
streamOut.println(MSG); // 서버에 메세지를 보내줍니다.
} catch (Exception ex) {
logger(ex.toString());
}
}
Handler mHandler = new Handler() { // 스레드에서 메세지를 받을 핸들러.
public void handleMessage(Message msg) {
switch (msg.what) {
case 0: // 채팅 메세지를 받아온다.
logger(msg.obj.toString());
break;
case 1: // 소켓접속을 끊는다.
try {
cSocket.close();
cSocket = null;
logger("접속이 끊어졌습니다.");
} catch (Exception e) {
logger("접속이 이미 끊겨 있습니다." + e.getMessage());
finish();
}
break;
}
}
};
class chatThread extends Thread {
private boolean flag = false; // 스레드 유지(종료)용 플래그
public void run() {
try {
while (!flag) { // 플래그가 false일경우에 루프
String msgs;
Message msg = new Message();
msg.what = 0;
msgs = streamIn.readLine(); // 서버에서 올 메세지를 기다린다.
msg.obj = msgs;
mHandler.sendMessage(msg); // 핸들러로 메세지 전송
if (msgs.equals("# [" + nickName + "]님이 나가셨습니다.")) { // 서버에서 온 메세지가 종료 메세지라면
flag = true; // 스레드 종료를 위해 플래그를 true로 바꿈.
msg = new Message();
msg.what = 1; // 종료메세지
mHandler.sendMessage(msg);
}
}
}catch(Exception e) {
logger(e.getMessage());
}
}
}
}
-------------------------------------------------------------------------------------------
- 서버 -
program.cs
-------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace chatServerTest
{
class Program
{
static void Main(string[] args)
{
BroadcastServer.start(10701);
}
}
}
-------------------------------------------------------------------------------------------
BroadcastServer.cs
-------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
namespace chatServerTest
{
class BroadcastServer
{
public static ArrayList socketList = new ArrayList(); //서버에 연결된 소켓들의 Array 입니다.
private static BroadcastServer broadcastServer;
private Thread threadWaitingSocket;
private Socket listener;
private int port;
public static void start(int _port) // 서버 시작
{
if (broadcastServer == null)
{
broadcastServer = new BroadcastServer(_port);
}
}
public static void stop() // 서버 종료
{
Console.WriteLine("서버를 종료합니다.");
foreach (SocketHandler socketHandler in socketList)
{
socketHandler.end();
}
if (broadcastServer != null)
{
broadcastServer.threadStop();
}
}
private void threadStop()
{
threadWaitingSocket.Abort();
listener.Close();
}
private BroadcastServer(int _port)
{
port = _port;
threadWaitingSocket = new Thread(new ThreadStart(WaitingSocket));
threadWaitingSocket.Start();
}
private void WaitingSocket() // 클라이언트의 접속을 체크하는 스레드.
{
IPAddress ipAddress = IPAddress.Any;
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(1000); // 동시에 접속할 접속자수를 설정
Console.WriteLine("연결을 기다립니다.");
while (true)
{
Socket acceptedSocket = listener.Accept(); // 접속한 클라이언트 소켓
string acceptedIP = ((IPEndPoint)acceptedSocket.RemoteEndPoint).Address.ToString(); // 접속한 클라이언트 IP
socketList.Add(new SocketHandler(acceptedSocket)); // 접속리스트에 추가
Console.WriteLine(socketList.Count + "번째 컴퓨터 - " + acceptedIP + "에서 접속하였습니다.");
}
}
}
public class SocketHandler
{
public Socket socket;
public Thread threadHandler;
public SocketHandler(Socket socket)
{
this.socket = socket;
threadHandler = new Thread(new ThreadStart(Handler));
threadHandler.Start();
}
public void Handler() // 실질적인 서버작업
{
byte[] buffer = new byte[4096];
int bufferCount;
SendMsg((BroadcastServer.socketList.Count) + "명이 접속해 있습니다.");
try
{
while (true)
{
buffer.Initialize();
bufferCount = socket.Receive(buffer);
if (bufferCount == 0) break;
string Msgs = ASCIIEncoding.UTF8.GetString(buffer);
byte[] byteimsi = new byte[bufferCount]; // 남은버퍼 없애기용 임시byte
for (int i = 0; i < bufferCount; i++)
{
byteimsi[i] = buffer[i];
}
Msgs = ASCIIEncoding.UTF8.GetString(byteimsi);
Console.WriteLine("클라이언트에서 받은 메세지" + Msgs);
SendMsg(Msgs);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
Console.WriteLine("클라이언트가 종료하였습니다.");
BroadcastServer.socketList.Remove(this);
socket.Close();
socket = null;
}
}
public void SendMsg(string Msg) // 메세지 보내기.
{
int bufferCount = 0;
byte[] buffer = new byte[4096];
buffer = ASCIIEncoding.UTF8.GetBytes(Msg);
bufferCount = ASCIIEncoding.UTF8.GetByteCount(Msg);
foreach (SocketHandler socketHandler in BroadcastServer.socketList)
{
socketHandler.socket.Send(buffer, 0, bufferCount, SocketFlags.None);
}
}
public void end()
{
threadHandler.Abort();
}
}
}
-------------------------------------------------------------------------------------------
[출처] 안드로이드용 채팅프로그램 클라이언트(java), 서버(c#) 소스|작성자 섬놈