博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Socket通信——C++server端和Javaclient
阅读量:5021 次
发布时间:2019-06-12

本文共 6330 字,大约阅读时间需要 21 分钟。

一句话来说就是。C++和Java 通过socket进行通信、传输数据。通过发送“字节流”就可以。

字节对于C++和java来说是通用的。可是传输的过程有很多问题须要注意,我为了弄清楚这个过程,查了一些资料,做了一些整理。

 不了解C++ socket编程,能够看这篇博客:

Linux 下:socket通信(Linux下,C/C++语言):http://blog.csdn.net/giantpoplar/article/details/47657303

Windows下:winsock:http://blog.csdn.net/giantpoplar/article/details/47657317

不了解Java socket编程,能够看这篇博客:

Java socket通信:http://blog.csdn.net/giantpoplar/article/details/47657325

不了解字节数组和基本数据类型的转换,能够看这篇博客

byte[]和 整形、浮点型数据的转换-java代码:http://blog.csdn.net/giantpoplar/article/details/47657333

 

在server向client发数据的时候。可能採取下面两种方式

server端直接发送struct

假设在编程时在C++端直接发送一个结构体,须要把这个结构体的指针强制转换为char*,通过一个个的字节传输

Msg message;retVal = send(Client, (char*)&message,sizeof(Msg), 0);
假设採用这样的方式,在client收到数据后进行解释。须要对
C++对象的内存布局有一个简单的了解。相同,假设你不了解,能够看这篇:
简单C++对象的内存布局:http://blog.csdn.net/giantpoplar/article/details/47658679

另外假设你的server端用了java,以ObjectOutputStream的方式写出一个对象,须要对java对象的内存布局有所了解,相同,假设你不了解。能够看这篇: 简单Java对象的内存布局:http://blog.csdn.net/giantpoplar/article/details/47657377

 server端把struct的每个成员单独发送

另一种方式是不把整个结构体整个发过去,而是一个一个变量发过去,这时候server和client两边要知道这些变量的相互顺序,一个一个一次接受就可以,这就涉及到字节数组和基本数据类型之间的转换。

 这个时候要注意server和client整数的表示方式是否一样,是不是都是大端法或者都是小端法,浮点数表示是否都符合IEEE 754规范。

否则两边要协调好。或者浮点数直接传字符串,尽管会带来效率损失,可是能够统一起来。

这两种问题都有缺点,首先就是大端表示,小端表示。不同的处理器採用的表示方式可能不同,可能当前执行正常,但可能带来的潜在的错误。

第二就是假设struct里面包括指针。它所指向的数据并不在struct的实例里面。可能会和使用者的想法相违背,这样的情况下使用“序列化”可能是更好的选择,这里找到一个简单的介绍http://www.infoq.com/cn/news/2014/06/flatbuffers。

我遇到的一些问题

server端在发送数据时一次发送的大小不要太大,比方我在发送一个538字节的Msg时。发生了传输异常的问题。我在本机測试正常,不再同一台机器上时就会出问题。

要注意:发送端和接收端接受的数据大小要同样。比方一次发128字节。接受也要一次接受128字节,否则easy造成丢包。粘包之类的问题。传输数据异常;

一次发的不要太大,太大也easy出问题;

要想更可靠,自己能够再定义一个协议,每次发数据时包括进去包的长度。校验码等信息

//2016年1月5日补

学习了计算机网络之后,知道了问题的解决办法。先占个坑

http://stackoverflow.com/questions/4835893/tcp-socket-question

//2016年1月5日补

以下附上我近期在写的一个程序,基本功能有了,但还不是非常完好

由于我的server和client肯定都是小端模式存贮整数,所以就临时没考虑传输时的字节顺序的问题

写一个Message类是为了将来把一些方法放进去用着比較方便。

Javaclient

import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.UnknownHostException;public class JavaClient{	public static void main(String[] args) throws UnknownHostException,			IOException, ClassNotFoundException {		//client		Socket s = new Socket("127.0.0.1", 8899);		InputStream is = s.getInputStream();		byte msg[] = new byte[536];				while (is.read(msg, 0, 536) > -1) {			Message m = new Message(msg);			if(m.guesture!=0)System.out.println(m.guesture);		}}}public class Message {	float left_hand[] = new float[66];//左手关节数据[X0 Y0 Z0 X1 Y1 Z1...X21 Y21 Z21]	float right_hand[] = new float[66];//右手关节数据	short left;//是否检測到左手  1 为检測到, 0为未检測到	short right;//是否检測到右手	short guesture;//手势	short alert_type;//警告类型	public Message(byte[] msg){//从字节数组构造一个message对象		for(int i=0 ; i<66 ; i++){			left_hand[i] = byte2float(msg, 4* i);		}		for(int i=0 ; i<66 ; i++){			right_hand[i] = byte2float(msg,264 + 4 * i);		}		left 		 =  getShort(msg, 528);		right		 =  getShort(msg, 530);		guesture	 =  getShort(msg, 532);		alert_type   =  getShort(msg, 534);	}//数组顺序依照“小端顺序”	private float byte2float(byte[] b, int index) {//4个字节转float 	    int l;                                             	    l = b[index + 0];                                  	    l &= 0xff;                                         	    l |= ((long) b[index + 1] << 8);                   	    l &= 0xffff;                                       	    l |= ((long) b[index + 2] << 16);                  	    l &= 0xffffff;                                     	    l |= ((long) b[index + 3] << 24);                  	    return Float.intBitsToFloat(l);                    	}  	private short getShort(byte[] bytes,int index){//两个字节转short          return (short) ((0xff & bytes[index+0]) | (0xff00 & (bytes[index+1] << 8)));      }  	}
C++服务端

#include
#include
#include
#pragma comment(lib, "ws2_32.lib")#ifndef MSG_#define MSG_struct Msg{ pxcF32 left_hand[66]; pxcF32 right_hand[66]; pxcI16 left; pxcI16 right; pxcI16 guesture; pxcI16 alert_type;};//消息结构#endifInt main(){WSADATA wsad; //WSADATA变量 SOCKET Server; //server套接字 SOCKET Client; //client套接字 SOCKADDR_IN addrServ; //server地址 int retVal; //返回值 //初始化套接字动态库 if (WSAStartup(MAKEWORD(2, 2), &wsad) != 0) { std::printf("初始化套接字动态库失败!\n"); return 1; } //创建套接字 Server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == Server) { std::printf("创建套接字失败!\n"); WSACleanup();//释放套接字资源; return -1; } //server套接字地址 addrServ.sin_family = AF_INET; addrServ.sin_port = htons(8899); addrServ.sin_addr.s_addr = INADDR_ANY; //绑定套接字 retVal = bind(Server, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN)); if (SOCKET_ERROR == retVal) { std::printf("绑定套接字失败!\n"); closesocket(Server); //关闭套接字 WSACleanup(); //释放套接字资源; return -1; } //開始监听 retVal = listen(Server, 1); if (SOCKET_ERROR == retVal) { std::printf("监听失败!\n"); closesocket(Server); //关闭套接字 WSACleanup(); //释放套接字资源; return -1; } for (;;){ //接受client请求 sockaddr_in addrClient; int addrClientlen = sizeof(addrClient); Client = accept(Server, (sockaddr FAR*)&addrClient, &addrClientlen); std::printf("accept a socket\n"); if (INVALID_SOCKET == Client) { std::printf("接受client请求失败!\n"); continue; // closesocket(Server); //关闭套接字 // WSACleanup(); //释放套接字资源; // return -1; } //发送client数据 while (true){ WaitForSingleObject(full_sem, INFINITE);//down操作 //WaitForSingleObject(mutex, INFINITE);//多个消费者须要加相互排斥信号量 Msg message = MsgQueue[head]; head = (head + 1) % QUEUE_LENGTH; //ReleaseSemaphore(mutex, 1, NULL);//up操作 ReleaseSemaphore(empty_sem, 1, NULL);//up操作 retVal = send(Client, (char*)&message, sizeof(Msg), 0); if (SOCKET_ERROR == retVal) { std::printf("接收client请求失败!\n"); //closesocket(Server); //关闭套接字 closesocket(Client); //关闭套接字 break; //return -1; } Sleep(100); } //std::printf("%s\n", buf); //输出来自Client的字符串 //退出 //closesocket(Server); //关闭套接字 closesocket(Client); //关闭套接字 } closesocket(Server); WSACleanup(); //释放套接字资源; return 0;}

说明:

本文由giantpoplar发表于CSDN

文章地址 http://blog.csdn.net/giantpoplar/article/details/47658929

转载请保留本说明

转载于:https://www.cnblogs.com/jzdwajue/p/6801532.html

你可能感兴趣的文章
js 正计时和倒计时
查看>>
复合数据类型,英文词频统计
查看>>
you-get帮助使用手册
查看>>
nyoj756_重建二叉树_先序遍历
查看>>
sin()函数的实现
查看>>
图像切割之(一)概述
查看>>
JAVA修饰符类型(public,protected,private,friendly)
查看>>
flex利用webservice上传照片
查看>>
IOS开发之Bug--使用KVC的易错情况
查看>>
python list和tuple
查看>>
基础薄弱的反思
查看>>
ORACLE增删改查以及case when的基本用法
查看>>
[转]oracle10客户端PL/SQL Developer如何连接远程服务器上的oracle数据库
查看>>
HTML5 表单元素和属性
查看>>
SDUTOJ 2498 数据结构实验之图论十一:AOE网上的关键路径
查看>>
使用SpringSocial开发QQ登录
查看>>
好玩的游戏
查看>>
2.6. Statistical Models, Supervised Learning and Function Approximation
查看>>
代码说明call和apply方法的区别 (咱们这方面讲解的少,这样的题有变式,需要举例讲解一下)...
查看>>
T-SQL 类型转换
查看>>