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