자바로 만든 서버와 c 로 만든 클라이언트간에 데이타는 어떻게

vudghkzm의 이미지

자바로 만든 서버가 있고, C로 만든 클라이언트가 있습니다.
이 둘간에 데이타를 주고 받고 싶습니다.

자바 서버에서 클라이언트로 데이타를 보낼 때는 큰 문제가 없습니다. 헌데 클라이언트에서 서버쪽으로 데이타를 보낼때, 서버에서 그 데이타를 받는것에 약간 문제가 있습니다.

서버에서는 DataInputStream 인스턴스를 이용해서 데이타를 읽을려고 시도하고 있습니다. readUTF() 메쏘드는 사용할 수 없는 것으로 알고 있기 때문에 byte[]를 사용하는 read() 메쏘드를 이용할려고 하고 있습니다. 헌데, C로 만든 클라이언트에서는 데이타의 길이를 먼저 전송해주지 않기 때문에 얼마만큼의 데이타가 오는지 가늠을 할 수가 없어서 byte[] 형 변수의 크기를 얼마만큼 설정을 해야 할지 알수가 없는 상태입니다...

위와 같은 상황에서 클라이언트에서 오는 메세지를 받는 가장 좋은 방법은 무엇인가요?
그리고 일반적으로 자바로 만든 서버와 C/C++ 로 만들어진 클라이언트간에 데이타를 주고 받을 때 일반적으로 어떻게 하는지요?

peccavi의 이미지

자바를 잘 몰라서 말씀드리기가 좀 조심스럽습니다만,

Quote:
헌데, C로 만든 클라이언트에서는 데이타의 길이를 먼저 전송해주지 않기 때문에 얼마만큼의 데이타가 오는지 가늠을 할 수가 없어서

이부분이 잘 이해가 안됩니다.

어떤 통신이던 간에 서로 약속해놓지 않는 이상(심지어는 이런 경우까지도)

상대방으로부터 어느정도의 크기를 받을지 예상할 수 없지 않나요?

그렇기 때문에 일반적으로 패킷에 상대방이 리시브할 사이즈를 포함해 데이터를 전송하는걸로 알고 있습니다.

----
jai guru deva om...

jongwooh의 이미지

자바 서버와 C 클라이언트가 무슨 API를 써서 주고 받는지는 모르겠지만 사용하신 API가 소켓이라고 가정해보자면, UDP 소켓일 경우 미리 한번의 최대 전송량을 정해두시고 그 크기만큼의 버퍼를 잡아서 읽으십시오.
TCP소켓일 경우 시스템이 알아서 패킷을 잘라주지만 API 위에서는 끊김없는 스트림으로 처리하는데, 어플리케이션은 미리 할당한 버퍼의 크기만큼을 읽으시면 됩니다.
데이타를 끊는 단위는 중간에 Delimiter 로 쓰는 식별자를 넣으시거나 (보통 텍스트 위주 프로토콜이면 \r\n 으로 구분하면 디버깅시 출력하면서 읽기도 좋음) 해서 읽는 쓰레드(프로세스)에서 메시지 단위로 재조립하시면 됩니다.

you must know the power of dark side.

익명 사용자의 이미지

자바프로그램에서 -> C프로그램으로 데이터를 보낼때는 상관없지만

C프로그램 -> 자바프로그램으로 보낼때는 "\r\n"을 데이터의 맨 마지막에 넣어줘야 자바에서 끝임을 알고 출력합니다.

자바는 특성상... 데이터의 끝이란 캐리지 문자를 받지 않으면 계속 데이터가 넘어온다고 생각하고 기다립니다.
그러므로 "\r\n"를 데이터의 마지막에 추가시켜주고
자바 소스 자체에서는 flush()를 이용해 버퍼를 비워야 메세지가 출려됩니다.

익명 사용자의 이미지

서버에 \r\n을 어디에 추가해야되나요??
클라이언트에 fflush를 쓰려는데 어디에써야하나요??

#include
#include
#include
#include
#include
#include
#define SERVER_PORT 3000

int Socket(int family, int type, int protocol);
void Bind(int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen);
void Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);

int main(void)
{
int server_socket;
int client_socket;

int nSockOpt;

struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int addrsize, msgsize;

char BUFF[1024] = { 0, };
fd_set readfd;
int maxfd;
int client_index;
int start_index;
int client_fd[5] = { 0 };
server_socket = Socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&(server_addr.sin_zero), 0, 8);
nSockOpt = 1;
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &nSockOpt, sizeof(nSockOpt));
Bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));

Listen(server_socket, 10);
FD_ZERO(&readfd);
maxfd = server_socket;
client_index = 0;

while (1)
{
FD_SET(server_socket, &readfd);

for (start_index = 0; start_index < client_index; start_index++)
{
FD_SET(client_fd[start_index], &readfd);

if (client_fd[start_index] > maxfd)
maxfd = client_fd[start_index];
}
maxfd = maxfd + 1;

select(maxfd, &readfd, NULL, NULL, NULL);


if (FD_ISSET(server_socket, &readfd))
{
if (client_index == 5)
break;
addrsize = sizeof(struct sockaddr_in);
client_socket = Accept(server_socket, (struct sockaddr*)&server_addr, &addrsize);
FD_SET(client_socket, &readfd);

client_fd[client_index] = client_socket;
client_index++;

}

for (start_index = 0; start_index < client_index; start_index++)
{
if (FD_ISSET(client_fd[start_index], &readfd))
{
memset(BUFF, '\0', sizeof(BUFF));

msgsize = read(client_fd[start_index], BUFF, sizeof(BUFF));
if (msgsize <= 0)
continue;
printf("Client Message>>%s", BUFF);

strcpy(BUFF, "Hello World!");

msgsize = strlen(BUFF);
write(client_fd[start_index], BUFF, msgsize);
}
}
}
return 0;

}
int Socket(int family, int type, int protocol)
{
int result = 0;
result = socket(family, type, protocol);
if (result == -1)
{
printf("Socket Contructing Error\n");
exit(0);
}
return result;
}
void Bind(int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen)
{
int result = 0;
result = bind(sockfd, socketaddr, addrlen);
if (result == -1)
{
printf("Socket Binding Error\n");
exit(0);
}
else
{
printf("Success Binding\n");
}

}
void Listen(int sockfd, int backlog)
{
int result = 0;
result = listen(sockfd, backlog);
if (result == -1)
{
printf("Listening Error\n");
exit(0);
}
else
{
printf("Success Listening\n");
}
}

int Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen)
{
int result = 0;
result = accept(sockfd, cliaddr, addrlen);
if (result == -1)
{
printf("Accept Error\n");
exit(0);
}
else
{
printf("Success Accept\n");
}
return result;

}

================================================
package com.example.rasp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SensormainActivity extends Activity {

private Socket socket;
BufferedReader socket_in;
PrintWriter socket_out;
EditText input;
Button button;
TextView output;
String data;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sensor);

input = (EditText) findViewById(R.id.input);
button = (Button) findViewById(R.id.button);
output = (TextView) findViewById(R.id.output);
button.setOnClickListener(new OnClickListener(){
public void onClick(View v){
String data = input.getText().toString();
Log.w("NETWORK",""+data);
if(data != null){
socket_out.println(data);
}
}
});
Thread worker = new Thread() {
public void run() {
try {
socket = new Socket("203.250.133.240", 3000);
socket_out = new PrintWriter(socket
.getOutputStream(), true);
socket_in = new BufferedReader(
new InputStreamReader(socket
.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
try {
while (true) {
data = socket_in.readLine();
output.post(new Runnable() {
public void run() {
output.setText(data);
}
});
}
} catch (Exception e) {
}
}
};

worker.start();
}

@Override
protected void onStop() {
super.onStop();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.