c++builer與java之間的socket通訊
C++builer與java都提供了功能豐富的socket控制項/類。這裡將實現c++builer與java之間的socket通訊,
能夠使雙方互相發送資訊。
在C++builer裡,我們採用 ServerSocket控制項做為伺服器端,java裡採用Socket類做為用戶端。
本樣本中互相發送的都為結構體,在C++builer裡定義為
typedef struct
{
int int1;
float f;
char ch[20];
double d;
} TMyMsg;
java裡發送部分是直接用的DataOutputStream 的writeXXX方法,當然也可以用內部類轉換成byte[]進行發送。
原始碼如下:
C++builer伺服器端
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <winsock.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ServerSocket1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnSendClick(TObject *Sender)
{
//發送的資料要進行位元組序轉換.
TMyMsg sendmsg;
sendmsg.int1 = htonl(30);
sendmsg.f = ntohf(12.345);
strcpy(sendmsg.ch,"測試資料!");
sendmsg.d = ntohd(67.890);
ServerSocket1->Socket->Connections[0]->SendBuf(&sendmsg, sizeof(TMyMsg));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
MemoSend->Lines->Add("int : 30");
MemoSend->Lines->Add("float : 12.345");
MemoSend->Lines->Add("char [20] : 測試資料!");
MemoSend->Lines->Add("double : 67.890");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
//接收的資料位元組序轉換
TMyMsg remsg;
Socket->ReceiveBuf(&remsg,sizeof(TMyMsg));
int int1 = ntohl(remsg.int1);
float f = ntohf(remsg.f);
char *ch = new char[20];
strcpy(ch,remsg.ch);
AnsiString sch = StrPas(ch);
double d = ntohd(remsg.d);
delete [] ch;
MemoRec->Lines->Add(int1);
MemoRec->Lines->Add(f);
MemoRec->Lines->Add(sch.Trim());
MemoRec->Lines->Add(d);
}
//---------------------------------------------------------------------------
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ScktComp.hpp>
#pragma pack(1) //位元組對齊
//---------------------------------------------------------------------------
typedef struct
{
int int1;
float f;
char ch[20];
double d;
} TMyMsg;
//---------------------------------------------------------------------------
//ntohf 與ntohd函數為網上收錄
float ntohf(float f)
{
unsigned char *p, p0, p1;
if(ntohs(1) ==1) return f;
p =(unsigned char *)&f;
p0 =p[0];
p1 =p[1];
p[0] =p[3];
p[3] =p0;
p[1] =p[2];
p[2] =p1;
return f;
}
//---------------------------------------------------------------------------
double ntohd(double d)
{
unsigned char *p, p0, p1, p2, p3;
if(ntohs(1) ==1) return d;
p =(unsigned char *)&d;
p0 =p[0];
p1 =p[1];
p2 =p[2];
p3 =p[3];
p[0] =p[7];
p[7] =p0;
p[1] =p[6];
p[6] =p1;
p[2] =p[5];
p[5] =p2;
p[3] =p[4];
p[4] =p3;
return d;
}
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TServerSocket *ServerSocket1;
TButton *Button1;
TLabel *Label1;
TMemo *MemoSend;
TLabel *Label2;
TMemo *MemoRec;
TButton *BtnSend;
void __fastcall Button1Click(TObject *Sender);
void __fastcall BtnSendClick(TObject *Sender);
void __fastcall FormShow(TObject *Sender);
void __fastcall ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
java用戶端
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
/*
* 建立日期 2006-5-10
*
* TODO 要更改此產生的檔案的模板,請轉至
* 視窗 - 喜好設定 - Java - 代碼樣式 - 代碼模板
*/
/**
* @author zwx
*
* TODO 要更改此產生的類型注釋的模板,請轉至 視窗 - 喜好設定 - Java - 代碼樣式 - 代碼模板
*/
public class SocketClientDemo extends JFrame {
int port = 2345;
String host = "localhost";
Socket socket;
JButton jbConnect = new JButton("串連");
JButton jbSend = new JButton("發送");
JTextArea jTASend = new JTextArea(7, 10);
JTextArea jTARec = new JTextArea(7, 10);
public SocketClientDemo() {
super("用戶端");
Container cp = this.getContentPane();
cp.setLayout(new FlowLayout());
cp.add(jbConnect);
cp.add(jbSend);
jbSend.addActionListener(jbSendAL); //發送按鈕
jbConnect.addActionListener(jbConnectAL); //連線按鍵
cp.add(jTARec);
jTARec.append("接收的內容");
cp.add(jTASend);
jTASend.append("發送的內容");
jTASend.append("/nint : 88");
jTASend.append("/nfloat : 77.66");
jTASend.append("/nString : From JAVA");
jTASend.append("/ndouble : 23.45");
this.setSize(250, 200);
this.setLocation(100, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new SocketClientDemo();
}
ActionListener jbConnectAL = new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
//執行個體化Socket ,並接收C++builder伺服器端發送的資料
socket = new Socket(InetAddress.getByName(host), port);
DataInputStream in = new DataInputStream(socket .getInputStream());
int int1 = in.readInt();
float f = in.readFloat();
byte[] buffer = new byte[20];
in.read(buffer);
String ch = new String(buffer);
double d = in.readDouble();
jTARec.append("/n" + Integer.toString(int1));
jTARec.append("/n" + Float.toString(f));
jTARec.append("/n" + ch.trim());
jTARec.append("/n" + Double.toString(d));
}//try
catch (IOException ex) {
ex.printStackTrace();
}
}
};
ActionListener jbSendAL = new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
//發送給伺服器端
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
int int1 = 88;
float f = (float) 77.66;
String ch = "From JAVA";
double d = 23.45;
out.writeInt(int1);
out.writeFloat(f);
byte[] buf = new byte[20];
System.arraycopy(ch.getBytes(),0,buf,0,ch.length());
out.write(buf,0,buf.length);
out.writeDouble(d);
}//try
catch (IOException ex) {
ex.printStackTrace();
}
}
};
}
由於c/c++語言編的程式的資料存放區順序跟編譯平台機器的CPU有關,而java程式則採用大位元組序,網路位元組序也採用大位元組序儲存,
因此C++builer的發送與接收函數都要先把資料進行位元組序轉換。另外還要注意位元組對齊問題,本例中C++builder的結構體是一位元組對齊。
運行介面如下:
運行時先啟動伺服器端,點擊“啟動伺服器端”按鈕。再啟動用戶端,選串連,先發送服務端的資料,再發送用戶端的資料。關閉時先關閉伺服器端。
有任何問題,歡迎指正。 E-mail:weixing979@163.com