C++用socket 做服务端,Java做客户端 可以通信吗

C++用socket 做服务端,Java做客户端 可以通信吗,第1张

可以通信的,因为C++和JAVA都是使用SOCKET编程,因此C++写的服务器,JAVA做客户端是能够通信的。我也经常使用PYTHON搭建一个服务器,因为PYTHON提供了SOCKET库,这个库跨平台也很好用。我的同事在写温湿度监控的后台服务器(java),就是连接到我用python写的服务器进行测试的。
如果说你的通信不上,那么先要检测,能否互相ping通,其次搞清楚C++服务器在局域网还是外网,如果是自己搭的服务器还需要考虑这个端口映射问题。如果这些都没问题就是通信不上,你就要通过wireshark等抓包工具查一下TCP/IP的三次握手了。一般来说,调用socket的API时系统都会通过返回值告诉你实际连接上没有,如果是通信不上,多半是通信协议这一块没做好。
如果有不懂的,欢迎进一步提问

Close只是通知底层socket关闭而已,并不一定保证底层的链接一定释放了,所以你一下子创建那么多链接肯定出问题
备注
Close 方法可关闭远程主机连接,并释放所有与 Socket 关联的托管资源和非托管资源。关闭后,Connected 属性将设置为 false。
对于面向连接的协议,建议先调用 Shutdown,然后再调用 Close 方法。这可以确保在已连接的套接字关闭之前,已发送和接收该套接字上的所有数据。
如果需要在不首先调用 Shutdown 的情况下调用 Close,则可以将 DontLinger Socket 选项设置为 false,并指定一个非零的超时间隔,从而确保排队等待输出的数据得到发送。这样,Close 将会一直阻止到发送完该数据或指定的时限超时为止。如果将 DontLinger 设置为 false,并且指定了一个非零的超时间隔,Close 将会释放连接并自动放弃排队等待输出的数据。
补充:
那就没办法了,你只能限制你的链接数量,可能你的底层的负荷量达不到那么大吧,不行你找其他的socket通信类库试试

之前写过这样的一个小程序,我发布在自己的博客上:>

Serverc

#include <WinSock2h>
#include <WS2tcpiph>
#include <cstdio>
#include <iostream>
// for file read
#include <fstream>
#include <string>
int main() {
/ load the initializer library /
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
/ list the each fields of wsaData /
// printf("wVersion: %d\n", wsaDatawVersion); // 514
// printf("wHighVersion: %d\n", wsaDatawHighVersion); // 514
// printf("iMaxSockets: %d\n", wsaDataiMaxSockets); // 0
// printf("iMaxUdpDg: %d\n", wsaDataiMaxUdpDg); // 0
/ you may not print the lpVendorInfo /
// printf("szDescription: %s\n", wsaDataszDescription); // WinSock 20
// printf("szSystemStatus: %s\n", wsaDataszSystemStatus); // Running
/ create socket(address family, type, protocol) /
int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/ initialize the addrinfo hints /
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hintsai_family = AF_INET;
hintsai_socktype = SOCK_STREAM;
hintsai_protocol = IPPROTO_TCP;
hintsai_flags = AI_PASSIVE;
struct addrinfo result = nullptr;
/ by hints, and then get the result(a linked list, see fields below) /
getaddrinfo(NULL, "8080", &hints, &result);
/ the member fiekds of result /
// printf("ai_family: %d\n", result->ai_family); // 2
// printf("ai_socktype: %d\n", result->ai_socktype); // 1
// printf("ai_protocol: %d\n", result->ai_protocol); // 6
// printf("ai_flags: %d\n", result->ai_flags); // 0
// printf("ai_canonname: %s\n", result->ai_canonname); // (null)
// printf("ai_a ddrlen: %d\n", result->ai_addrlen); // 16
// printf("ai_addr->sa_family: %d\n", result->ai_addr->sa_family); // 2
// printf("ai_addr->sa_data: %s\n", result->ai_addr->sa_data); // 
// printf("ai_next: %x\n", result->ai_next); // 0
/ bind the socket to a address /
/ bind(socket, sockaddr name, name len) /
bind(socket_fd, result->ai_addr, result->ai_addrlen);
freeaddrinfo(result);
/ listen the socket /
/ listen(socket, backlog) /
listen(socket_fd, SOMAXCONN); / 0x7fffffff /
while(true) {
/ accept a connection /
/ accept(socket, addr, addrlen) /
int client_fd = accept(socket_fd, nullptr, 0);
printf("New Connection Eastablished\n");
/ Now we send the source code of this file to client /
std::ifstream fin("c:\\sourcecpp");
/ store it into a buffer /
while (fingood()) {
// I rememeber there is a method called getline
std::string s;
getline(fin, s);
// we need a new line
s = s + '\n';
send(client_fd, sc_str(), ssize(), 0);
}
finclose();
/ close client socket /
closesocket(client_fd);
}
/ may be never invoked /
closesocket(socket_fd);
WSACleanup();
return 0;
}

Clientc

#include <WinSock2h>
#include <cstdio>
#include <iostream>
#include <fstream>
int main() {
/ load the initializer library /
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
/ create socket /
int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/ connect /
sockaddr_in addr;
addrsin_family = AF_INET;
addrsin_addrs_addr = inet_addr("127001");
addrsin_port = htons(8080);
/ connect(socket, sockaddr, namelen) /
connect(socket_fd, (sockaddr)&addr, sizeof(addr));
/ buffer memory /
char buf[1024];
/ open a file for write /
std::ofstream fout("sourcecpp", std::ios_base::trunc);
while (true) {
int read = recv(socket_fd, buf, 1024, 0); 
if (read == 0) {
foutclose();
printf("Connection Closed\n");
break;
}
if (read > 1024) {
printf("Buffer Overflow\n");
} else {
buf[read - 1] = 0;
/ now we can print the bytes from server /
fout << buf << std::endl;
}
}
/ close socket /
closesocket(socket_fd);
WSACleanup();
return 0;
}

不是很复杂。具体思路:
1在服务器端写一个程序,这程序进行读取数据库中你想要的数据,然后再通过socket服务端发送给客户端。
2写个socket客户端 。
android的不知道是不是这样!

using SystemNet;
using SystemNetSockets;
static void Main(string[] args)//服务器段
{
int port = 2000;
string host = "127001";
//
///创建终结点(EndPoint)
IPAddress ip = IPAddressParse(host);//把ip地址字符串转换为IPAddress类型的实例
IPEndPoint ipe = new IPEndPoint(ip, port);//用指定的端口和ip初始化IPEndPoint类的新实例
//
///创建socket并开始监听
Socket s = new Socket(AddressFamilyInterNetwork, SocketTypeStream, ProtocolTypeTcp);//创建一个socket对像,如果用udp协议,则要用SocketTypeDgram类型的套接字
sBind(ipe);//绑定EndPoint对像(2000端口和ip地址)
sListen(0);//开始监听
ConsoleWriteLine("等待客户端连接");
//
///接受到client连接,为此连接建立新的socket,并接受信息
Socket temp = sAccept();//为新建连接创建新的socket
ConsoleWriteLine("建立连接");
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = tempReceive(recvBytes, recvBytesLength, 0);//从客户端接受信息
recvStr += EncodingASCIIGetString(recvBytes, 0, bytes);
//
///给client端返回信息
ConsoleWriteLine("server get message:{0}", recvStr);//把客户端传来的信息显示出来
string sendStr = "ok!Client send message successful!";
byte[] bs = EncodingASCIIGetBytes(sendStr);
tempSend(bs, bsLength, 0);//返回信息给客户端
tempClose();
sClose();
ConsoleReadLine();
}
static void Main(string[] args)//客户端
{
try
{
int port = 2000;
string host = "127001";
//
///创建终结点EndPoint
IPAddress ip = IPAddressParse(host);
//IPAddress ipp = new IPAddress("127001");
IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndpoint实例
//
///创建socket并连接到服务器
Socket c = new Socket(AddressFamilyInterNetwork, SocketTypeStream, ProtocolTypeTcp);//创建Socket
ConsoleWriteLine("Conneting…");
cConnect(ipe);//连接到服务器
//
///向服务器发送信息
string sendStr = "hello!This is a socket test";
byte[] bs = EncodingASCIIGetBytes(sendStr);//把字符串编码为字节
ConsoleWriteLine("Send Message");
cSend(bs, bsLength, 0);//发送信息
//
///接受从服务器返回的信息
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = cReceive(recvBytes, recvBytesLength, 0);//从服务器端接受返回信息
recvStr += EncodingASCIIGetString(recvBytes, 0, bytes);
ConsoleWriteLine("client get message:{0}", recvStr);//显示服务器返回信息
//
///一定记着用完socket后要关闭
cClose();
}
catch (ArgumentNullException e)
{
ConsoleWriteLine("argumentNullException: {0}", e);
}
catch (SocketException e)
{
ConsoleWriteLine("SocketException:{0}", e);
}
ConsoleWriteLine("Press Enter to Exit");
}

要完成这个工作,需要完成三个部分的工作,以下依次说明:
一、建立服务器类
Java中有一个专门用来建立Socket服务器的类,名叫ServerSocket,可以用服务器需要使用的端口号作为参数来创建服务器对象。
ServerSocket server = new ServerSocket(9998)
这条语句创建了一个服务器对象,这个服务器使用9998号端口即在端口9998上注册服务,这里稍微要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的,另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。当一个客户端程序建立一个Socket连接,所连接的端口号为9998时,服务器对象server便响应这个连接,并且serveraccept()方法会创建一个Socket对象。服务器端便可以利用这个Socket对象与客户进行通讯。
Socket incoming = serveraccept() ; // 监听窗口,等待连接
进而得到输入流和输出流,并进行封装
BufferedReader in = new BufferedReader(new
InputStreamReader(incominggetInputStream()));
/
当读取文件时,先把内容读到缓存中,当调用inreadLine()时,再从缓存中以字符的方式读取数据(以下简称“缓存字节读取方式”)。
/
PrintWriter ut = new PrintWriter(incominggetOutputStream(),true);
随后,就可以使用inreadLine()方法得到客户端的输入,也可以使用outprintln()方法向客户端发送数据。从而可以根据程序的需要对客户端的不同请求进行回应。
在所有通讯结束以后应该关闭这两个数据流,关闭的顺序是先关闭输出流,再关闭输入流,即使用
outclose();
inclose();
二、建立客户端代码
相比服务器端,客户端要简单一些,客户端只需用服务器所在机器的ip以及服务器的端口作为参数创建一个Socket对象。得到这个对象后,就可以用"建立服务器"部分介绍的方法实现数据的输入和输出。
Socket socket = new Socket("1681601242",9998);
或:
Socket socket = new Socket(InetAddressgetLocalHost(),5678); // 向主机名为InetAddressgetLocalHost()的服务器申请连接
客户机必须知道有关服务器的IP地址,对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供,它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法。
in = new BufferedReader(new InputStreamReader(socketgetInputStream()));
out = new PrintWriter(socketgetOutputStream(),true);
以上的程序代码建立了一个Socket对象,这个对象连接到ip地址为1681601242的主机上、端口为9998的服务器对象。并且建立了输入流和输出流,分别对应服务器的输出和客户端的写入。
三、实例分析
服务方:
import javaio;
import javanet;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678); //在端口5678上注册服务
Socket client=serveraccept(); // 监听窗口,等待连接
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
BufferedReader serverInput=new BufferedReader(new InputStreamReader(Systemin));
PrintWriter ut=new PrintWriter(clientgetOutputStream());
while(true){
String str=inreadLine(); //// 读取从client传来的数据信息
str = serverInputreadLine(); // 读取用户键盘输入的字符串
Systemoutprintln(str); //服务器控制台输出数据信息
outprintln("has receive"); //服务器向客户端发送信息:has receive
outflush();
if(strequals("end"))
break;
}
clientclose();
}
}
这个程序的主要目的在于服务器不断接收客户机所写入的信息只到,客户机发送"End"字符串就退出程序,并且服务器也会做出"Receive"为回应,告知客户机已接收到消息。
客户机代码:
import javanet;
import javaio;
public class Client{
static Socket server;
public static void main(String[] args)throws Exception{
server=new Socket(InetAddressgetLocalHost(),5678); // 向主机名为InetAddressgetLocalHost()的服务器申请连接
BufferedReader in=new BufferedReader(new InputStreamReader(servergetInputStream())); //客户端建立输入流并进行封装
PrintWriter ut=new PrintWriter(servergetOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(Systemin)); //客户端从键盘输入信息
while(true){
String str=wtreadLine(); //客户端读取(获得)键盘的字符串
String str1=inreadLine(); // 从服务器获得字符串
outprintln(str); //客户端向服务器发送信息
outflush();
if(strequals("end")){
break;
}
Systemoutprintln(inreadLine());
}
serverclose();
}
}
客户机代码则是接受客户键盘输入,并把该信息输出,然后输出"End"用来做退出标识。
这个程序只是简单的两台计算机之间的通讯,如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的。那么多个客户端如何实现呢
其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身,而服务器通过accept方法就是同意和客户建立通讯这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯,那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下:
服务器:
import javaio;
import javanet;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
Socket client=serveraccept();
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
PrintWriter ut=new PrintWriter(clientgetOutputStream());
while(true){
String str=inreadLine();
Systemoutprintln(str);
outprintln("has receive");
outflush();
if(strequals("end"))
break;
}
clientclose();
}
}
}
这里仅仅只是加了一个外层的While循环,这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的"End"消息那么现在就实现了多客户之间的交互了。但是问题又来了,这样做虽然解决了多客户,可是是排队执行的。也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互,无法做到同时服务,那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了。所以线程是最好的解决方案。
那么下面的问题是如何使用线程首先要做的事情是创建线程并使得其可以和网络连线取得联系。然后由线程来执行刚才的 *** 作,要创建线程要么直接继承Thread要么实现Runnable接口,要建立和Socket的联系只要传递引用就可以了而要执行线程就必须重写run方法,而run方法所做的事情就是刚才单线程版本main所做的事情,因此我们的程序变成了这样:
import javanet;
import javaio;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
thisclient=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
PrintWriter ut=new PrintWriter(clientgetOutputStream());
//Mutil User but can't parallel
while(true){
String str=inreadLine();
Systemoutprintln(str);
outprintln("has receive");
outflush();
if(strequals("end"))
break;
}
clientclose();
}catch(IOException ex){
}finally{
}
}
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(serveraccept());
mustart();
}
}
}
我的类直接从Thread类继承了下来并且通过构造函数传递引用和客户Socket建立了联系,这样每个线程就有了。一个通讯管道同样我们可以填写run方法,把之前的 *** 作交给线程来完成,这样多客户并行的Socket就建立起来了。

呵呵,当让可以了。
1、首先我说一下他们的关系:
一个解决方案(sln)中可以包含多个项目(vcxproj);
这些项目可以是互不相关的,也可以是相关的;
2、下面说如何将你的两个项目放在同一个解决方案里
你将一个的项目(B)拷贝到另外一个项目中(A)(其中文件夹A和B中含有vcxproj);
你有Avcxproj和Bvcxproj两个项目,他们分别为
文件夹A(其中含有Avcxproj) 和 文件夹B(其中含有Bvcxproj)
解决方案(Csln)和文件夹A和B在同一目录下。
然后打开对应的解决方案,添加项目,将刚才的B项目添加即可;
3、设置启动项目。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10632348.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存