一、阻塞模式套接字服务端和客户端的运行流程如下:

1.1 服务器运行过程如下:

1.服务器启动后,等待客户端的连接请求。
2.当收到客户端的请求后,在界面上显示该客户端的IP地址和端口,以及“Hello,Server!”问候语。
3.服务器向该客户端应答“Hello,Clinet!”问候语。
4.服务器退出。
1.2客户端运行过程如下:
1.客户端启动后,向服务器发起连接请求。
2.当连接请求被接受后,客户端向服务器发送“Hello,Server!”问候语。
3.等待服务器的应答。
4.当客户端收到服务器的“Hello,Clinet!”应答后,客户端退出。

1.3 客户端和服务器端工作流程如下:

二、实例

2.1 服务器端:Server.cpp

 #include<iostream>
#include<winsock2.h>
#include<string>
#pragma comment(lib,"ws2_32.lib")
using namespace std; #define SERVER_EXIT_OK 0
#define SERVER_DLL_ERROR 1
#define SERVER_API_ERROR 2
#define SERVERPORT 8888
#define MAX_NUM_BUF 64 //全局变量
char bufRecv[MAX_NUM_BUF];//读缓冲区
char bufSend[MAX_NUM_BUF];//写缓冲区
SOCKET sServer;//服务器监听套接字
SOCKET sClient;//接受客户端套接字
bool bConning;//与客户端的连接状态变量 //函数
void InitMember(void);
void ShowSocketMsg(char* str);
int HandleSocketError(char* str);
BOOL RecvLine(SOCKET s, char *buf);//读取一行数据
BOOL SendLine(SOCKET s,char * buf);//发送一行数据
int ExitClient(int nExit);//退出程序 int main(int argc,char*argv[])
{
//调用初始化函数,进行相关初始化工作
InitMember();
//Windows Sockets动态库初始化
WORD wVersionRequseted;
WSADATA wsaData;
int retVal;
wVersionRequseted = MAKEWORD(,);
retVal = WSAStartup(wVersionRequseted,&wsaData);
if (retVal!=)
{
ShowSocketMsg("初始化动态连接库失败");
return SERVER_DLL_ERROR;
}
//确保Winsock dll支持2.2
if (LOBYTE(wsaData.wVersion)!=||HIBYTE(wsaData.wVersion!=))
{
ShowSocketMsg("没有发现动态链接库");
return SERVER_DLL_ERROR;
}
//创建套接字
sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET==sServer)
{
return HandleSocketError("Faild socket()!");
}
//服务器套接字地址
SOCKADDR_IN addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(SERVERPORT);
addrServer.sin_addr.S_un.S_addr = INADDR_ANY;
//绑定套接字
retVal = bind(sServer,(sockaddr*)&addrServer,sizeof(addrServer));
if (SOCKET_ERROR==retVal)
{
closesocket(sServer);
return HandleSocketError("绑定套接字失败");
}
//监听
retVal = listen(sServer,);
if (SOCKET_ERROR==retVal)
{
closesocket(sServer);
return HandleSocketError("监听失败");
}
cout << "服务器开始初始化成功!" << endl;
cout << "等待客户端的连接...." << endl;
//接受客户端的请求
sockaddr_in addrClient;
int addrClientLen = sizeof(addrClient);
sClient = accept(sServer,(sockaddr*)&addrClient,&addrClientLen);
if (SOCKET_ERROR==sClient)
{
closesocket(sServer);
return HandleSocketError("接受客户端请求失败");
}
//显示客户端的IP和端口
char *pClientIP = inet_ntoa(addrClient.sin_addr);
u_short clientPort = ntohs(addrClient.sin_port);
cout << "接受到来自客户端的请求:" << endl;
cout << "客户端的IP:" << pClientIP << endl;
cout << "客户端的端口:" << clientPort << endl;
//接受客户端的数据
if (!RecvLine(sClient,bufRecv))
{
return ExitClient(SERVER_API_ERROR);
}
//显示客户端的数据
cout << bufRecv << endl;
//向客户端发送数据
strcpy(bufSend,"hello,client!\n");
if (!SendLine(sClient,bufSend))
{
return ExitClient(SERVER_API_ERROR);
}
//显示退出信息
cout << "服务器正在退出>>>>>" << endl;
//退出
return ExitClient(SERVER_EXIT_OK);
getchar();
return ;
} //初始化成员变量
void InitMember(void)
{
//初始化缓冲区
memset(bufRecv, , MAX_NUM_BUF);
memset(bufSend, , MAX_NUM_BUF);
//初始化
sServer = INVALID_SOCKET;
sClient = INVALID_SOCKET;
//无连接状态
bConning = FALSE; }
void ShowSocketMsg(char* str)
{
MessageBox(NULL,(LPCWSTR)str,(LPCWSTR)"SERVER_ERROR",MB_OK);
} int HandleSocketError(char * str)
{
ShowSocketMsg(str);//显示错误
WSACleanup();//卸载Windows socket DLL
return SERVER_API_ERROR;//退出应用程序
} BOOL RecvLine(SOCKET s, char * buf)
{
BOOL retVal=TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = ; //读入字节数
int nDataLen = ; //数据长度
while (!bLineEnd&&bConning) //与客户端连接,没有换行
{
nReadLen = recv(s,buf+nDataLen,,);
//错误处理
if (SOCKET_ERROR==nReadLen)
{
int nErrorCode = WSAGetLastError();
if (WSAENOTCONN==nErrorCode)
{
ShowSocketMsg("套接字未连接");
}
else if (WSAESHUTDOWN==nErrorCode)
{
ShowSocketMsg("套接字已经关闭");
}
else if (WSAETIMEDOUT == nErrorCode)
{
ShowSocketMsg("连接已断开!");
}
else if (WSAECONNRESET == nErrorCode)
{
ShowSocketMsg("一个现存的远程主机上运行的客户端被强制关闭!");
}
else {} retVal = FALSE; //读数据失败
break;
} if (nReadLen==)//客户端关闭
{
retVal = FALSE;
break;
}
//读入数据
if (*(buf+nDataLen)=='\n')
{
bLineEnd = TRUE;//接受数据结束
}
else
{
nDataLen += nReadLen;//增加数据长度
}
} return retVal;
} BOOL SendLine(SOCKET s, char * buf)
{
int retVal=;//返回值
retVal = send(s, buf, strlen(buf), );//一次发送
//错误处理
if (SOCKET_ERROR == retVal)
{
int nErrCode = WSAGetLastError();//错误代码
if (WSAENOTCONN == nErrCode)
{
ShowSocketMsg("套接字未连接"); }
else if (WSAESHUTDOWN == nErrCode)
{
ShowSocketMsg("套接字已关闭!"); }
else if (WSAETIMEDOUT == nErrCode)
{
ShowSocketMsg("连接已断开!");
}
else {} return FALSE; //发送失败
} return TRUE;
} int ExitClient(int nExit)
{
closesocket(sServer); //关闭监听套接字
closesocket(sClient); //关闭连接客户端套接接
WSACleanup(); //卸载Windows sockets DLL 清理内存
return nExit; //退出
}

2.2 客户端:Client.cpp

 #include <windows.h>
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "wsock32.lib")
using namespace std; #define CLIENT_EXIT_OK 0 //客户端正常退出
#define CLIENT_DLL_REEOR 1 //调用Windows socket dll失败
#define CLIENT_API_ERROR 2 //调用Windows socket api失败
#define MAX_NUM_BUF 64 //缓冲区的最大长度
#define SERVERPORT 8888//服务器TCP端口 //变量
char bufRecv[MAX_NUM_BUF]; //读缓冲区
char bufSend[MAX_NUM_BUF]; //写缓冲区
SOCKET sHost; //socket
BOOL bConning; //连接服务器状态 //函数
void InitMember(void); //初始化变量
int ExitClient(int nExit); //退出
BOOL RecvLine(SOCKET s, char* buf); //读取一行数据
void ShowErrorMsg(void); //显示错误信息 //主函数
int main()
{ //初始化变量
InitMember(); WORD wVersionRequested; //应用程序需要Windows sockets DLL的版本
WSADATA wsaData; //Windows sockets DLL版本信息
int retVal=; //调用Windows sockets API返回值 //初始化Windows Sockets DLL
wVersionRequested = MAKEWORD(, );
retVal = WSAStartup(wVersionRequested, (LPWSADATA)&wsaData);
if ( != retVal)
{
MessageBox(NULL, (LPCWSTR)"初始化动态链接库失败!",(LPCWSTR) "ERROR", MB_OK);
return CLIENT_DLL_REEOR;
} //创建Windows socket
sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sHost)
{
ShowErrorMsg(); //显示错误信息
WSACleanup(); //释放资源
return CLIENT_API_ERROR;//退出
} //准备连接服务器
cout << "客户端初始化成功!" << endl;
cout << "准备连接到服务器..." << endl; //获取主机的信息
LPHOSTENT hostEntry;
char hostname[MAX_NUM_BUF];
gethostname(hostname, MAX_NUM_BUF); //获取主机名称
hostEntry = gethostbyname(hostname); //获取主机信息
if (!hostEntry)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//设置sockaddr_in
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
addrServ.sin_port = htons(SERVERPORT);
//连接服务器
retVal = connect(sHost, (sockaddr*)&addrServ, sizeof(addrServ));
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
else {
bConning = TRUE; //连接服务器成功
}
//连接服务器成功
cout << "连接服务器成功!" << endl; //向服务器发送数据
strcpy_s(bufSend, "Hello,Server!\n");
retVal = send(sHost, bufSend, strlen(bufSend), );
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
} //从服务器接收数据
if (!RecvLine(sHost, bufRecv))
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//显示服务器的应答
cout << bufRecv << endl; //退出
return ExitClient(CLIENT_EXIT_OK);
} /*
* 显示错误信息
*/
void ShowErrorMsg(void)
{
int nErrCode = WSAGetLastError();//获取错误代码 HLOCAL hlocal = NULL; //获取错误的文本字符串
BOOL fOk = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, nErrCode, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(PTSTR)&hlocal, , NULL); //显示错误信息
if (hlocal != NULL)
{
MessageBox(NULL, (LPCWSTR)LocalLock(hlocal), (LPCWSTR)"CLIENT ERROR", MB_OK);
LocalFree(hlocal);
}
} /*
* 初始化成员变量
*/
void InitMember(void)
{
//初始化读和写缓冲区
memset(bufRecv, , MAX_NUM_BUF);
memset(bufSend, , MAX_NUM_BUF);
//初始化
sHost = INVALID_SOCKET;
//没有连接状态
bConning = FALSE;
} /*
* 退出
*/
int ExitClient(int nExit)
{
closesocket(sHost); //关闭套接字
WSACleanup(); //卸载Windows sockets DLL 清理内存 //显示退出信息
cout << "客户端正在退出..." << endl;
Sleep();
return nExit; //退出
} /*
* 读取一行数据
*/
BOOL RecvLine(SOCKET s, char* buf)
{
BOOL retVal = TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = ; //读入字节数
int nDataLen = ; //数据长度
while (!bLineEnd && bConning) //与客户端连接 没有换行
{
nReadLen = recv(s, buf + nDataLen, , );//每次接收一个字节
//错误处理
if (SOCKET_ERROR == nReadLen)
{
retVal = FALSE; //读数据失败
break; //跳出循环
} if ( == nReadLen)//客户端关闭
{
retVal = FALSE; //读数据失败
break; //跳出循环
} //读入数据
if ('\n' == *(buf + nDataLen)) //换行符
{
bLineEnd = TRUE; //接收数据结束
}
else {
nDataLen += nReadLen; //增加数据长度
}
} return retVal;
}

windows套接字阻塞模式编程实例的更多相关文章

  1. TCP/UDP套接字 java socket编程实例

    网络协议七层结构: 什么是Socket? socket(套接字)是两个程序之间通过双向信道进行数据交换的端,可以理解为接口.使用socket编程也称为网络编程,socket只是接口并不是网络通信协议. ...

  2. windows套接字相关函数

    windows套接字相关函数 作者:vpoet mail:vpoet_sir@163.com 我们学习TCP/IP协议无非是利用这些协议进行通信开发,然而如果让我们自己来直接根据协议规则和协议格式来进 ...

  3. 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .

    命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...

  4. 缺少网络连接需要的Windows套接字注册表项(浏览器无法连网)

      缺少网络连接需要的Windows套接字注册表项(浏览器无法连网) CreateTime--2018年4月25日14:17:42 Author:Marydon 1.异常信息 此计算机上缺少一个或多个 ...

  5. Python中利用原始套接字进行网络编程的示例

    Python中利用原始套接字进行网络编程的示例 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构 ...

  6. 基于TCP的socket套接字的网络编程(客户端/服务端模式)

    于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...

  7. java套接字(socket)实例

    客户端socket 流程: 1.连接远程主机 2.发送数据 3.接收数据 4.关闭流与socket连接 实例: import java.io.*; import java.net.Socket; im ...

  8. 5-tcp套接字服务端编程

    import socket 1.创建套接字 sockfd= socket.socket(socket_family = AF_INIT,socket_type=SOCK_STREAM,proto) 功 ...

  9. iptables开启后造成本地套接字阻塞的问题

    前段时间,我使用iptables实现了针对IP地址与MAC地址的白名单功能,即将INPUT链的默认规则设为DROP: iptables -P INPUT DROP 这样就能拒绝一切外来报文.随后只需要 ...

随机推荐

  1. BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings

    以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...

  2. ubuntu 安装 tar.gz 文件

    ubuntu 安装 tar.gz 文件 本文链接:https://blog.csdn.net/caloriesung/article/details/81536144 tar zxvf FileNam ...

  3. HDU 6191 Query on A Tree(字典树+离线)

    Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Othe ...

  4. sqli-lab(15)

    要考四级了 翻译过来就是 基于时间的单引号盲注 0X01盲注 的了解 https://www.cnblogs.com/ldhbetter/p/9201840.html 这里写的清清楚楚 A 先拆解长度 ...

  5. android 3.0 ationbar使用总结

    1,ationbar的基本讲解 http://www.apkbus.com/forum.php?mod=viewthread&tid=125536 仅仅需要根据需求写出一个menu资源文件 2 ...

  6. PHP mac localhost 环境下发送邮件

    转载自:http://mabblog.com/blog/2011/09/lion-smtp-postfix-relay-and-dreamhost/ When developing web-apps ...

  7. Hive数据导入Elasticsearch

    Elasticsearch Jar包准备 所有节点导入elasticsearch-hadoop-5.5.1.jar /opt/cloudera/parcels/CDH-5.12.0-1.cdh5.12 ...

  8. [LeetCode]-DataBase-Trips and Users

    The Trips table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are b ...

  9. async await task.Result 卡死

    在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...

  10. Android传感器【转】

    本文转载自:http://blog.csdn.net/ffmxnjm/article/details/52101592?locationNum=3&fps=1 传感器的意义 事实上,目前智能手 ...