C++编写的多线程通信程序,代码编译没有错误(vc),可是服务端与客户端就是连接不上,望高手解答

C++编写的多线程通信程序,代码编译没有错误(vc),可是服务端与客户端就是连接不上,望高手解答,第1张

我调试了你的代码,你的代码是没有问题的,虽然不能使用,但是正常的Socket通讯流程是可以进行的。而且我调试的时候服务器和客户端代码都返回通讯成功。accept()返回的socket为124,connect返回0,说明通讯是正常的。你需要从操作系统环境找原因了。

 

调试截图如下:

 

服务器端accept返回socket为124

 

 

 

客户端connect返回0

 

 

定时器:使用SystemTimersTimer类 SystemTimersTimer t = new SystemTimersTimer(10000);//实例化Timer类,设置间隔时间为10000毫秒; tElapsed += new SystemTimersElapsedEventHandler(theout);//到达时间的时候执行事件; tAutoReset = true;//设置是一直执行(true)还是执行一次(false); tEnabled = true;//是否执行SystemTimersTimerElapsed事件; public void theout(object source, SystemTimersElapsedEventArgs e) { MessageBoxShow("OK!"); } 多线程方面:

我以前写过类似的socket通信,虽然你用的方法和我的不太一样,但我还是感觉有一些问题

接受消息的时候,你用的是while(true)循环,当第一次将消息接受后,缓冲区就为空了,我想你再用循环去接收应该会出问题。

我记得有个poll方法,具体什么用途忘记了(很久没写代码了)你在循环里面加个if (clientsocketPoll(1000, SelectModeSelectRead))判断语句“clientsocket为你需要接收消息的socket”看看能不能解决,或者就用异步也可以,我可以发一下我以前的代码你参考下:

using System;

using SystemCollectionsGeneric;

using SystemComponentModel;

using SystemData;

using SystemDrawing;

using SystemText;

using SystemWindowsForms;

using SystemNet;

using SystemNetSockets;

using SystemThreading;

namespace test4_2

{

public partial class Form1 : Form

{

Socket connectSocket;

//Socket client;

byte[] bytes = new byte[1024];

delegate void listboxDel(string s);

listboxDel listboxdel;

public Form1()

{

InitializeComponent();

textBoxContentFocus();

listboxdel = new listboxDel(listbox);

//为连接指派线程

Thread threadConnect = new Thread(new ThreadStart(Connect));

threadConnectStart();

}

public void listbox(string str)

{

listBox1ItemsAdd(str);

listBox1SelectedIndex = listBox1ItemsCount - 1;

listBox1ClearSelected();

}

//连接方法

public void Connect()

{

try

{

//建立连接socket

connectSocket = new Socket(AddressFamilyInterNetwork,SocketTypeStream,ProtocolTypeTcp);

//开始异步连接

connectSocketBeginConnect(IPAddressParse("1721694152"),

82,

new AsyncCallback(ConnectCallback), //定义回调函数代理

connectSocket); //传递给回调函数的状态

}

catch (Exception e)

{

MessageBoxShow(eMessage);

}

}

//连接方法的回调函数

private void ConnectCallback(IAsyncResult ar)

{

try

{

//从传递的状态中获取套接字,创建一个客户端套接字

Socket client = (Socket)arAsyncState;

//完成挂起的连接操作

clientEndConnect(ar);

listBox1Invoke(listboxdel, "连接服务器成功,可以开始通话!");

clientBeginReceive(bytes, 0, 1000, 0, new AsyncCallback(receivecallback), client);

}

catch (Exception e)

{

ConsoleWriteLine(eToString());

}

}

public void receivecallback(IAsyncResult ar)

{

try

{

Socket client = (Socket)arAsyncState;

int length = clientEndReceive(ar);

listBox1Invoke(listboxdel, EncodingUTF8GetString(bytes, 0, length));

clientBeginReceive(bytes, 0, 1000, 0, new AsyncCallback(receivecallback), client);

}

catch

{

}

}

//发送方法

private void Send(String data)

{

//使用ASCII转换字符串为字节序列

byte[] byteData = EncodingUTF8GetBytes(data); //将字符串转换成字节序列

//开始向远端设备发送数据

connectSocketBeginSend(byteData, 0, byteDataLength, SocketFlagsNone,

new AsyncCallback(SendCallback), connectSocket);

}

//发送方法的回调函数

private void SendCallback(IAsyncResult ar)

{

try

{

//从传递的状态中获取套接字,创建一个客户端套接字

Socket client = (Socket)arAsyncState;

//结束异步数据传输操作,返回传输的字节数

int bytesSent = clientEndSend(ar);

listBox1Invoke(listboxdel, textBoxUserText +":"+ textBoxContentText);

}

catch (Exception e)

{

MessageBoxShow(eToString());

}

}

private void buttonSend_Click(object sender, EventArgs e)

{

Send(textBoxUserText+":"+textBoxContentText);

}

}

}

1、使用socekt通信一般步骤

1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。

2)客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。

3)服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesocket()关闭套接字。

2、多个客户端同时连接在一个服务器上

这时候服务器端应该使用多线程,每连接上一个客户端就给该客户端开启一个线程。监听端口的时候也要单独开一个线程、不然会阻塞主线程。这样做有一个明显的缺点,就是有N个客户端请求连接时,就会有N个线程,对程序的性能和计算机的性能影响很大,可以使用线程池进行管理。

使用线程池的好处:主要用于减少因频繁创建和销毁线程带来开销,因此那些经常使用且执行时间短的线程需要用线程池来管理。

3、C#版代码如下

服务器端代码:

[html] view plain copy

using System;

using SystemCollectionsGeneric;

using SystemLinq;

using SystemText;

using SystemNet;

using SystemNetSockets;

using SystemThreading;

using SystemIO;

namespace SockServer

{

class Program

{

static void Main(string[] args)

{

try

{

//把ip地址转换为实例

IPAddress ipa = IPAddressParse("127001");

//监听端口8001

TcpListener mylsn = new TcpListener(ipa, 8001);

//开启监听

mylsnStart();

//输出监听成功的信息

ConsoleWriteLine("在8001启动服务,等待连接");

//等待处理接入连接请求

while (true)

{

Socket mysock = mylsnAcceptSocket();

ConsoleWriteLine("有连接,连接来自" + mysockRemoteEndPoint);

work w = new work();

wmysock = mysock;

wmylsn = mylsn;

Thread t = new Thread(new ThreadStart(wmain));

tStart();

}

}

catch

{ }

finally

{ }

}

}

class work

{

public Socket mysock;

public TcpListener mylsn;

public void main()

{

//接收客户端消息

byte[] data = new byte[100];

mysockReceive(data);

string rt = SystemTextUTF8EncodingUTF8GetString(data);

ConsoleWriteLine(rt);

//给客户端发消息

mysockSend(UTF8EncodingUTF8GetBytes("server callback"));

//释放资源

mysockClose();

mylsnStop();

}

}

}

客户端代码:

[html] view plain copy

using System;

using SystemCollectionsGeneric;

using SystemLinq;

using SystemText;

using SystemNet;

using SystemNetSockets;

using SystemThreading;

using SystemIO;

namespace SockClient

{

class Program

{

public static void Main()

{

//新建客户端套接字

TcpClient tclient = new TcpClient();

//连接服务器

tclientConnect("127001", 8001);

ConsoleWriteLine("输入要发送的消息");

//读入要传输的字符

string str = ConsoleReadLine();

//得到流

Stream stm = tclientGetStream();

//发送字符串

ASCIIEncoding asen = new ASCIIEncoding();

byte[] data = asenGetBytes(str);

stmWrite(data, 0, dataLength);

//接受服务器返回的消息

byte[] back = new byte[100];

int k = stmRead(back, 0, 100);

//输出服务器返回的消息

for (int i = 0; i < k; i++)

{

ConsoleWrite(ConvertToChar(back[i]));

}

//关闭连接

tclientClose();

}

}

}

程序分Server和Client

服务器端打开侦听的端口,一有客户端连接就创建两个新的线程来负责这个连接

一个负责客户端发送的信息(ClientMsgCollectThread 类),

另一个负责通过该Socket发送数据(ServerMsgSendThread )

Serverjava代码如下:

/

创建日期 2009-3-7

TODO 要更改此生成的文件的模板,请转至

窗口 - 首选项 - Java - 代码样式 - 代码模板

/

package faueMutiUser;

import javaioBufferedReader;

import javaioIOException;

import javaioInputStreamReader;

import javaioPrintWriter;

import javanetServerSocket;

import javanetSocket;

/

服务器端

@author Faue

/

public class Server extends ServerSocket {

private static final int SERVER_PORT = 10000;

/

构造方法,用于实现连接的监听

@throws IOException

/

public Server() throws IOException {

super(SERVER_PORT);

try {

while (true) {

Socket socket = superaccept();

new Thread(new ClientMsgCollectThread(socket), "getAndShow"

+ socketgetPort())start();

new Thread(new ServerMsgSendThread(socket), "send"

+ socketgetPort())start();

}

} catch (IOException e) {

eprintStackTrace();

}

}

public static void main(String[] args) throws IOException {

new Server();

}

/

该类用于创建接收客户端发来的信息并显示的线程

@author Faue

@version 100

/

class ClientMsgCollectThread implements Runnable {

private Socket client;

private BufferedReader in;

private StringBuffer inputStringBuffer = new StringBuffer("Hello");

/

得到Socket的输入流

@param s

@throws IOException

/

public ClientMsgCollectThread(Socket s) throws IOException {

client = s;

in = new BufferedReader(new InputStreamReader(client

getInputStream(), "GBK"));

}

public void run() {

try {

while (!clientisClosed()) {

inputStringBufferdelete(0, inputStringBufferlength());

inputStringBufferappend(inreadLine());

Systemoutprintln(getMsg(inputStringBuffertoString()));

}

} catch (IOException e) {

//eprintStackTrace();

Systemoutprintln(clienttoString() + " is closed!");

}

}

/

构造显示的字符串

@param line

@return

/

private String getMsg(String line) {

return clienttoString() + " says:" + line;

}

}

/

该类用于创建发送数据的线程

@author Faue

@version 100

/

class ServerMsgSendThread implements Runnable {

private Socket client;

private PrintWriter out;

private BufferedReader keyboardInput;

private StringBuffer outputStringBuffer = new StringBuffer("Hello");

/

得到键盘的输入流

@param s

@throws IOException

/

public ServerMsgSendThread(Socket s) throws IOException {

client = s;

out = new PrintWriter(clientgetOutputStream(), true);

keyboardInput = new BufferedReader(new InputStreamReader(Systemin));

}

public void run() {

try {

while (!clientisClosed()) {

outputStringBufferdelete(0, outputStringBufferlength());

outputStringBufferappend(keyboardInputreadLine());

outprintln(outputStringBuffertoString());

}

} catch (IOException e) {

//eprintStackTrace();

Systemoutprintln(clienttoString() + " is closed!");

}

}

}

}

客户端:

实现基于IP地址的连接,连接后也创建两个线程来实现信息的发送和接收

/

创建日期 2009-3-7

/

package faueMutiUser;

import javaioBufferedReader;

import javaioIOException;

import javaioInputStreamReader;

import javaioPrintWriter;

import javanetSocket;

/

客户端

@author Faue

/

public class Client {

private Socket mySocket;

/

创建线程的构造方法

@param IP

@throws IOException

/

public Client(String IP) throws IOException {

try {

mySocket = new Socket(IP, 10000);

new Thread(new ServerMsgCollectThread(mySocket), "getAndShow"

+ mySocketgetPort())start();

new Thread(new ClientMsgSendThread(mySocket), "send"

+ mySocketgetPort())start();

} catch (IOException e) {

//eprintStackTrace();

Systemoutprintln("ServerIP:" + IP

+ " port:10000 can not be Connected");

}

}

public static void main(String[] args) throws IOException {

try {

new Client(args[0]);

} catch (Exception e) {

Systemoutprintln("输入的IP地址错误");

}

}

/

该类用于创建接收服务端发来的信息并显示的线程

@author Faue

@version 100

/

class ServerMsgCollectThread implements Runnable {

private Socket client;

private BufferedReader in;

private StringBuffer inputStringBuffer = new StringBuffer("Hello");

/

得到Socket的输入流

@param s

@throws IOException

/

public ServerMsgCollectThread(Socket s) throws IOException {

client = s;

in = new BufferedReader(new InputStreamReader(client

getInputStream(), "GBK"));

}

public void run() {

try {

while (!clientisClosed()) {

inputStringBufferdelete(0, inputStringBufferlength());

inputStringBufferappend(inreadLine());

Systemoutprintln(getMsg(inputStringBuffertoString()));

}

} catch (IOException e) {

//eprintStackTrace();

Systemoutprintln(clienttoString() + " is closed!");

Systemexit(0);

}

}

/

构造输入字符串

@param line

@return

/

private String getMsg(String line) {

return clienttoString() + " says:" + line;

}

}

/

该类用于创建发送数据的线程

@author Faue

@version 100

/

class ClientMsgSendThread implements Runnable {

private Socket client;

private PrintWriter out;

private BufferedReader keyboardInput;

private StringBuffer outputStringBuffer = new StringBuffer("Hello");

/

得到键盘的输入流

@param s

@throws IOException

/

public ClientMsgSendThread(Socket s) throws IOException {

client = s;

out = new PrintWriter(clientgetOutputStream(), true);

keyboardInput = new BufferedReader(new InputStreamReader(Systemin));

}

public void run() {

try {

while (!clientisClosed()) {

outputStringBufferdelete(0, outputStringBufferlength());

outputStringBufferappend(keyboardInputreadLine());

outprintln(outputStringBuffertoString());

}

outprintln("--- See you, bye! ---");

} catch (IOException e) {

//eprintStackTrace();

Systemoutprintln(clienttoString() + " is closed!");

Systemexit(0);

}

}

}

}

如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!

vaela

原理是这样的,服务器端有一个客户端管理器,负责管理所有连接进来的客户端,另外还需要为这个客户端管理器注册一个监听器,监听客户端的连接与断开两个动作,有客户端连接进来,就会触发监听器,监听器获取该客户端的在线好友列表,向在线的好友推送上线提醒消息,客户端断开时,也会出发监听器,监听器获取该客户端的在线好友列表,向在线的好友推送下线提醒消息

进程和线程是操作系统中的两个重要概念,本文将深入探讨它们的区别和联系。

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » C++编写的多线程通信程序,代码编译没有错误(vc),可是服务端与客户端就是连接不上,望高手解答

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情