关于c++中socket通信的问题望大神来给解决下

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于c++中socket通信的问题望大神来给解决下相关的知识,希望对你有一定的参考价值。

#include <iostream>
#include <Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define PORT 4000
#define IP_ADDRESS "192.0.0.1"
DWORD WINAPI ClientThread(LPVOID IpParameter)

SOCKET ClientScocket = (SOCKET)IpParameter;
int Ret = 0;
char RecvBuffer[MAX_PATH];
while(true)

//将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。
memset(RecvBuffer,0x00,sizeof(RecvBuffer));
//recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
Ret = recv(ClientScocket,RecvBuffer,MAX_PATH,0);
if (Ret == 0 || Ret == SOCKET_ERROR)

cout <<"客户端退出!"<< endl;
break;

cout <<"接收到客户端的信息为:"<< RecvBuffer <<endl;

return 0;

int main(int argc,char *argv[])

//这个结构被用来存储被WSAStartup函数调用后返回的Windows Sockets数据。它包含Winsock.dll执行的数据。
WSADATA Ws;
SOCKET ServerSocket,ClientScocket;
//此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息
struct sockaddr_in LocalAddr,ClientAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
//初始化windows套接字
//使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息
if (WSAStartup(MAKEWORD(2,2),&Ws) != 0)

cout <<"初始化windows套接字失败::" << GetLastError() << endl;
return -1;

//创建套接字
ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (ServerSocket == INVALID_SOCKET)

cout <<"创建windows套接字失败::" << GetLastError() << endl;
return -1;

LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero,0x00,8);
//捆绑套接字
Ret = bind(ServerSocket,(struct sockaddr *)&LocalAddr,sizeof(LocalAddr));
if (Ret != 0)

cout <<"捆绑套接字失败::" << GetLastError() << endl;
return -1;

Ret = listen(ServerSocket,10);
if (Ret != 0)

cout <<"监听套接字失败::" << GetLastError() << endl;
return -1;

cout <<"服务端已启动....."<< endl;
while(true)

AddrLen = sizeof(ClientAddr);
ClientScocket = accept(ServerSocket,(struct sockaddr *)&ClientAddr,&AddrLen);
if (ClientScocket == INVALID_SOCKET)

cout <<"接收失败::" << GetLastError() << endl;
break;

cout <<"客户端连接::"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;
hThread = CreateThread(NULL,0,ClientThread,(LPVOID)ClientScocket,0,NULL);
if (hThread == NULL)

cout <<"创建线程失败!"<< endl;
break;

CloseHandle(hThread);

closesocket(ServerSocket);
closesocket(ClientScocket);
WSACleanup();
system("pause");
return 0;


运行的话有个问题,报错误捆绑套接字失败即:
if (Ret != 0)

cout <<"捆绑套接字失败::" << GetLastError() << endl;
return -1;

这个函数报错,我实在不知道为什么,求解

参考技术A 看打印出来的 错误码 GetLastError() 是多少,WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEADDRINUSE:所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。
WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEAFNOSUPPORT:本协议不支持所指定的地址族。
WSAEINVAL:该套接口已与一个地址捆绑。
WSAENOBUFS:无足够可用缓冲区,连接过多。
WSAENOTSOCK:描述字不是一个套接口。
看情况 如果代码无误的话,最大的可能是端口被占用!追问

#define IP_ADDRESS "192.0.0.1"我自己找到了,是网址给错了。。。。无语

本回答被提问者采纳
参考技术B GetLastError()没有错误信息吗?追问

#define IP_ADDRESS "192.0.0.1"我自己找到了,是网址给错了。。。。无语

追答

这是一个提供很好检错的 函数。
host 一般可以定义为127.0.0.1

c语言socket通信问题,小弟菜鸟,求大神指导下,谢谢

SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);

if(CreateSocketToServer(sockClient))//已正确创建套接字

if(ConnectToServer(sockClient,flag))//已正确连到服务器

CString sendInfo,recvInfo;
sendInfo="Hello,Sever "+name+" "+passwd+"\n
if(SendInfoToServer(sockClient,sendInfo,flag))//已向服务器发送验证数据

cout<<"向服务器发送用户名和密码:"<<sendInfo<<endl;
recvInfo=RecvInfoFromServer(sockClient,flag);
MessageBox("接收到信息为:"+recvInfo);
if(recvInfo!="false")//得到服务器确认信息

cout<<"客户端接收到服务器响应:"<<recvInfo<<endl;
while(连接服务器成功)

/*我想在得到服务器的确认消息后,新建一个线程与服务端进行通信,但是while的判断
*语句条件是该socket连接仍然存在,但是我百度了下,都说socket不能使用两次connect,
* 那我这里应该怎么判断呢,谢谢各位...
*/




CloseSocketToServer(sockClient);

你可以在while()判断socket句柄是否有效,如果有效,然后,你再创建一个新的线程,线程里重新创建一个socket句柄,重新连接,然后通信。但是我觉得没有必要,你直接while判断句柄有效,然后直接用该句柄进行通信不好么。追问

恩,我明白你的意思了,我还有个问题,就是当程序运行过connect后,继续运行send操作后,这时我断开服务端后,应该是服务断开了呀,应该是接不到什么了,为什么客户端还会接受到一个空消息呢

追答

这是windows socket机制的问题,在windows下是返回一个空消息,在linux下是返回-1 但是在arm下,如果你断开了,但你没有判断就直接recv,那就会提示你段错误了

追问

非常感谢你的热心,还有个问题想问下哈,我将开始创建的socketClient传递到新建的线程中,在线程中新建了一个自己写的socket类的对象,使用该对象的SendInfoToServer(sockClient,sendInfo,flag)与服务器进行通信,想着同一个socketClient,为什么程序会报错socket error 10038即没有建立socket,这是怎么回事呢

追答

你是怎么传进去的,可能是你的传递方式有问题

追问

百度这里字数有限制,我给你发了百度的私信了,呵呵,帮我看下,实在是麻烦你了。。。。

追答

回你了

追问

谢谢你,哈哈,问题解决了,谢谢,学长....,同时谢谢以下各位的回答,真心感谢....

参考技术A 我不明白你为什么要用while。。。用if就可以了啊。。把SOCEKET的套接字传到线程里面,继续用这个套接字做通信接口,完成你的业务逻辑。追问

恩,我刚把它改成if了,,我还有个问题,就是当程序运行过connect后,继续运行send操作后,这时我断开服务端后,应该是服务断开了呀,应该是接不到什么了,为什么客户端还会接受到一个空消息呢

追答

空消息?你是说你发送了密码以后收到一个空消息?还是你发送全部完成以后closesocket以后收到一个空消息?

追问

感谢你哦,呵呵》。。。

参考技术B 把while也挪到新线程中去。

以上是关于关于c++中socket通信的问题望大神来给解决下的主要内容,如果未能解决你的问题,请参考以下文章

c语言socket通信问题,小弟菜鸟,求大神指导下,谢谢

java的客户端用的是Socket,服务器端用SocketChannel,这两种能实现通信么? 说得比较白,望理解

C++ socket传送和接收结构体问题,求大神帮忙

C++ 网络编程 01

关于socket

Java Socket通信介绍及可能遇到的问题解决_java - JAVA