iOS NSStream 이용한 채팅앱 예제
✅ iOS 네이티브 소스
SocketSessionViewController.h
#import <UIKit/UIKit.h>
@interface SocketSessionViewController : UIViewController <NSStreamDelegate>
@end
SocketSessionViewController.m
#import "SocketSessionViewController.h"
@interface SocketSessionViewController ()
//텍스트 필드
@property (weak, nonatomic) IBOutlet UITextField *idTextField;
@property (weak, nonatomic) IBOutlet UIView *sessionView;
@property (strong, nonatomic) NSMutableArray *messages;
@property (weak, nonatomic) IBOutlet UITextView *returnedDataTextField;
@property (strong, nonatomic) IBOutlet UIButton *closeStream;
- (IBAction)joinSessionButtonAction:(id)sender;
@end
//스트림 객체
NSInputStream *inputStream;
NSOutputStream *outputStream;
@implementation SocketSessionViewController
//스트림 닫기
- (IBAction)closeStreamAction:(id)sender {
NSLog(@"스트림 닫기");
[inputStream close];
[outputStream close];
}
- (void)viewDidLoad {
[super viewDidLoad];
//스트림 초기화
[self initNetworkCommunication];
_messages = [[NSMutableArray alloc]init];
self.idTextField.text = @"";
self.returnedDataTextField.text = @"";
}
- (void)initNetworkCommunication {
/*
여기있는 유일한 문제는 NSStream 클래스가 원격 호스트에 연결할 수없는 반면 CFStream은 가능하다!
NSStream과 CFStream은 일종의 브리지 연결이므로 NSStream 형식의 CFStream을 쉽게 가져올 수 있다.
*/
//원격 호스트에 연결 가능
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
//특정 호스트의 TCP / IP 포트에 연결된 읽기 및 쓰기 가능한 스트림을 생성
//두 스트림을 호스트와 포트에 바인딩하는 데 사용. 일단 호출하면 CFStream을 NSStream으로 자유롭게 캐스팅 가능하다.
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"172.20.10.4", 6666, &readStream, &writeStream);
// NSStream ==> CFStream 캐스팅
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
//스트림 델리게이트 설정
[inputStream setDelegate:self];
[outputStream setDelegate:self];
/*
스트림은 지속적으로 데이터를 보내거나받을 준비가되어 있어야 한다.
이 기능을 사용하려면 실행 루프에서 이벤트를 수신하도록 스트림을 예약해야한다.
NSRunLoop 스케줄링을 사용하면 다른 코드 (필요한 경우)를 실행할 수 있지만 스트림에서 문제가 발생하면 알림을받을 수 있습니다.
*/
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//스트림 열기
[inputStream open];
[outputStream open];
}
//쓰기
- (IBAction)joinSessionButtonAction:(id)sender {
NSString *response = [NSString stringWithFormat:@"%@\n",self.idTextField.text];
// NSString 을 UTF8 로 변환해서 raw stream 으로 쓴다.
const uint8_t * rawstring = (const uint8_t *)[response UTF8String];
//스트림에 쓰기
[outputStream write:rawstring maxLength:strlen((const char *)rawstring)];
self.idTextField.text = @"";
}
//스트림 델리게이트 메소드
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
//쓰기 콜백
case NSStreamEventHasSpaceAvailable: {
if(theStream == outputStream) {
NSLog(@"outputStream is ready.");
}
break;
}
//읽기 콜백
case NSStreamEventHasBytesAvailable:
NSLog(@"inputStream is ready.");
if (theStream == inputStream) {
uint8_t buffer[1024];
long len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding];
if (nil != output) {
NSLog(@"서버에서 받은 데이터: %@", output);
[self messageRevieved:output];
}
}
}
}
break;
//인풋, 아웃풋 스트림 열기
case NSStreamEventOpenCompleted:
NSLog(@"Stream 열었음.");
break;
//연결 실패
case NSStreamEventErrorOccurred:
NSLog(@"host에 연결 할 수 없습니다.");
break;
case NSStreamEventEndEncountered:
NSLog(@"NSStreamEventEndEncountered");
break;
default:
NSLog(@"Unknown event");
}
}
//받은 메시지 처리
-(void)messageRevieved:(NSString *)message {
NSLog(@"messageRevieved - 진입");
NSMutableString *messagesString = [NSMutableString stringWithString:self.returnedDataTextField.text];
[messagesString appendString:message];
self.returnedDataTextField.text = messagesString;
}
@end
소스
테이블 뷰 관련 소스
✅ Java Server Socket 소스
package zzzz;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("start main");
System.out.println("Welcome to the world of Socket");
//서버소켓
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(6666);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int i = 0;
while (true) {
Socket thisClient = null;
PrintWriter pw = null;
try {
System.out.print("connection requests from clients");
// accept 메소드는 프로세스를 차단합니다.
thisClient = serverSocket.accept();
System.out.println("There are a client socket requests consent.");
//연결 - 소켓이 열려있다면
while (!thisClient.isClosed()) {
// 인풋 스트림 소켓 읽기
InputStream is = thisClient.getInputStream();
//클라이언트가 보낸 내용
InputStreamReader clientInput = new InputStreamReader(is);
//버퍼로 변환
BufferedReader br = new BufferedReader(clientInput);
//ip
System.out.println("current socket client's IP address:" + thisClient.getInetAddress());
//클라이언트가 보낸 내용
String clientStr = br.readLine();
//출력
System.out.println("the client said:" + clientStr);
//값이 있다면
if(clientStr != null) {
// 클라이언트에 문자열 전송
pw = new PrintWriter(thisClient.getOutputStream());
pw.println(clientStr);
pw.flush();
//연결 종료
if (clientStr.equals("goodbye")) {
System.out.println("연결종료....1");
thisClient.close();
}
}else {
System.out.println("연결종료....2");
thisClient.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Read Input process flow will block the main process
i++;
}
}
}
✅ Java Client 소스 예제
public class startgo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String ip = "172.20.10.4";
int port = 5555;
new Client1(ip, port);
}
}
package zzz22clinet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client1 {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
public Client1(String ip, int port) {
try {
// 서버에 요청 보내기
socket = new Socket(ip, port);
System.out.println(socket.getInetAddress().getHostAddress() + "에 연결됨");
// 메시지 받기
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
// 메세지 전달
pw.println("메시지를 발송한다. 오버!");
pw.flush();
// 응답 출력
System.out.println(br.readLine());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
// 소켓 닫기 (연결 끊기)
try {
if(socket != null) { socket.close(); }
if(br != null) { br.close(); }
if(pw != null) { pw.close(); }
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
자바 IO 패키지 예제 - git
자바 스레드 예제 - git
'아이폰 개발 > ios 개념&튜토리얼' 카테고리의 다른 글
swift 직렬과 동시 & 동기와 비동기 개념 (0) | 2021.07.01 |
---|---|
ios dispatchequeue 1 (0) | 2021.06.30 |
iOS UIBezierPath 예제 - 그림 그리기 (0) | 2021.02.22 |
CGContextRef 예제 - 그림 그리기 (0) | 2021.02.22 |
iOS 카테고리 예제 - (UIColor 확장하기) (0) | 2021.02.21 |