Socket通信——C++server端和Javaclient

一句话来说就是。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<Windows.h>
#include<iostream>
#include<string.h>

#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;
};//消息结构
#endif

Int 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

转载请保留本说明

时间: 2024-10-12 19:11:42

Socket通信——C++server端和Javaclient的相关文章

进程对象的其他方法、守护进程、使用多进程实现 socket tcp协议 server端的并发(抢票程序)、队列、进程之间的通信(IPC)

# 进程对象的其他方法 from multiprocessing import Process import time class MyProcess(Process): def __init__(self, a, b): # 为了给子进程传递参数 super().__init__() self.a = a self.b = b def run(self): print("子进程开始执行") time.sleep(2) print("子进程结束", self.a,

使用多进程 实现socket tcp协议 server端的并发

server端: from multiprocessing import Process import socket def func(conn): while 1: conn.send(b'hello,this is server') if __name__ == '__main__': # 子进程会导入这句话上面的代码 sk = socket.socket() sk.bind(('127.0.0.1', 8888)) sk.listen() while 1: conn,addr = sk.a

Go语言中Socket通信TCP服务端

1.用法: (1)定义远程IP地址.使用net.ResolveTCPAddr()方法,定义一个TCP地址,做为本机监听地址. (2)使用net.ListenTCP("tcp",localAddress)方法开始监听,并返回tcpListener对像. (3)使用tcpListener.AcceptTCP方法进行接受连接.返回:net.TCPConn对像. (4)对net.TCPConn对像进行读写操作. (5)关闭连接. 2.代码: package main import ( &quo

python,socket网络编程,最简单的server端和client端代码

python网络编程三要素:网络地址,端口号,协议 知识点:conn代表的是客户端的socket对象. 下面的server.py和client.py小程序,实现了最简单的socket通信功能. #server.py import socket sk = socket.socket() address = ('127.0.0.1',8080) sk.bind(address) sk.listen(3) print('waitting......') conn,addr = sk.accept()

Flash Socket通信的安全策略问题 843端口

1.问题描述       将flash发布为html格式后,加载页面后,swf无法与服务器进行socket通信.Flash端显示的错误为:securityErrorHandler信息: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"] 在服务器端显示的信息是由客户端尝试进行连接,但是无法接受数据.接受的数据显

基于NIO的Socket通信

一.NIO模式的基本原理: 服务端: 首先,服务端打开一个通道(ServerSocketChannel),并向通道中注册一个通道调度器(Selector):然后向通道调度器注册感兴趣的事件SelectionKey(如:OP_ACCEPT),接着就可以使用通道调度器(Selector)轮询通道(ServerSocketChannel)上注册的事件,并进行相应的处理. 客户端: 客户端在请求与服务端通信时,也可以像服务器端一样注册感兴趣的事件(比服务端少了SelectionKey.OP_ACCEPT

TCP,UDP协议下的socket通信

TCP通信流程 Server端: 创建套接字:socket( ) 创建sockaddr_in结构体变量,并设置相关参数 将套接字与IP.端口绑定:bind( ) 使套接字处于监听状态,等待Client端发起连接请求:listen( ) 取接收请求,并生成已连接socket描述符:accept( ) 进行网络读写操作:read()/write() .recv()/send() 关闭套接字:close( ) Client端 创建套接字:socket( ) 创建sockaddr_in结构体变量,并设置

HTML5 Socket通信

HTML5 Socket通信使用起来也是相当不从的,先将部分JS代码与大家分享: var socket; function connect() { var host = "ws://" + $("serverIP").value + ":" + $("serverPort").value + "/" socket = new WebSocket(host); try { socket.onopen = fu

网络编程-SOCKET开发之----3. socket通信工作流程

1. TCP的socket通信流程 服务端 1)socket----创建socket对象. 2)bind----绑定本机ip+port. 3)listen----监听来电,若在监听到来电,则建立起连接. 4)accept----再创建一个socket对象给其收发消息.原因是现实中服务端都是面对多个客户端,那么为了区分各个客户端,则每个客户端都需再分配一个socket对象进行收发消息. 5)read.write----就是收发消息了. 客户端 1)socket----创建socket对象. 2)c