热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

TCP套接字编程实现

一、基于TCP的套接字编程实现流程:1.服务器端流程简介:(1)创建套接字(socket)(2)将套接字绑定到一个本地地
一、基于TCP的套接字编程实现流程:
1.  服务器端流程简介:
            (1)创建套接字(socket)
            (2)将套接字绑定到一个本地地址和端口上(bind)
            (3)将套接字设定为监听模式,准备接受客户端请求(listen)
            (4)阻塞等待客户端请求到来。当请求到来后,接受连接请求,返回一个新的对应于此客户端连接的套接字sockClient(accept)
            (5)用返回的套接字sockClient和客户端进行通信(send/recv);
            (6)返回,等待另一个客户端请求(accept)
            (7)关闭套接字(close)
2.  客户端流程简介:
            (1)  创建套接字(socket)
            (2)  向服务器发出连接请求(connect)
            (3)  和服务器进行通信(send/recv)
            (4)  关闭套接字(close)
                                                             
二、 send和recv函数的理解:
  当调用socket创建套接字时,同时在内核中生成发送和接收缓冲区。
  • 设置为connect模式时(客户端模式),调用send会将用户自定义的buff中的数据拷贝到发送缓冲区,缓冲区数据的发送由TCP/IP模型完成;

  • 设置为listen模式时(服务器端模式),发送缓冲区不再使用,接收缓冲区只存放客户端的连接请求。而accpet函数返回的新建套接字sockfd会再生成两个新缓冲区,发送和接收缓冲区。当调用recv时,recv先等待sockfd的发送缓冲区中数据按协议传送完毕,再检查sockfd的接收缓冲区,如果接收缓冲区没有数据或正在传送,则recv等待;否则recv将接收缓冲区中的数据拷贝到用户定义的buff中(ps:当接收缓冲区中数据长度大于buff长度时,recv要调用多次才能完全拷贝完成)。recv返回的是每次实际拷贝的数据长度,若拷贝出错则返回SOCKET_ERROR,若网络中断则返回0。

  • send和recv只是从发送/接收缓冲区中拷贝数据,真正的读写数据是由TCP/IP协议完成的

C++客户端/服务器端的简单实现:
(1)Sever实现:
#include 
#include

#include

#pragma comment(lib,"ws2_32.lib")
int main()
{
//1. 加载socket函数库
WSADATA wsaData;
SOCKET sockServer;
SOCKADDR_IN addrServer;
SOCKET sockClient;
SOCKADDR_IN addrClient;
WSAStartup(MAKEWORD(
2,2),&wsaData); //加载套接字库

//2. 创建套接字
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //INADDR_ANY表示任何IP,即允许所有的客户端连接到本地服务端
addrServer.sin_family = AF_INET; //设置为IP通信
addrServer.sin_port = htons(6000); //绑定端口6000
sockServer = socket(AF_INET,SOCK_STREAM,0); //创建流式套接字
std::cout<<"创建套接字成功"<<std::endl;

//3. 将套接字绑定到 固定IP和固定端口
bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); //进行端口和IP地址的绑定
std::cout<<"绑定套接字成功"<<std::endl;

//4. 将套接字设置为监听模式,等待连接到来
listen(sockServer,5); //监听队列为5
std::cout<<"监听连接中......"<<std::endl;
int len = sizeof(SOCKADDR);
char sendBuf[100]; //发送至客户端的字符串
char recvBuf[100]; //接受客户端返回的字符串

//5. 阻塞服务端的进程,直到有客户端连接为止
sockClient = accept(sockServer, (SOCKADDR*)&addrClient, &len); //sockClinet为返回的新的客户端连接
std::cout<<"收到连接:"<std::endl;

//6. 接收并打印客户端数据
int recvlen = 0;
if((recvlen = recv(sockClient,recvBuf,100,0)) > 0)
{
std::cout
<std::endl;
}
send(sockClient, "Receive the Client Data", 23, 0);

//7. 关闭socket
closesocket(sockClient);
WSACleanup();
return 0;
}

(2)Client实现:

#include   
#include

#include

#include

#pragma comment(lib, “ws2_32.lib”)

int main()
{
//1. 加载套接字
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf(”Failed to load Winsock”);
return;
}

//2. 创建套接字
SOCKADDR_IN addrSrv;
addrSrv.sin_family
= AF_INET;
addrSrv.sin_port
= htons(6000); //端口号6000
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //访问的服务器IP
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); //创建客户端套接字

//3. 向服务器发出连接请求
if(connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET)
{
std::cout
<<"Connect failed:"<std::endl;
return;
}

//4.接收和发送数据
char recvbuff[1024];
memset(recvbuff,
0, sizeof(recvbuff));
recv(sockClient, recvbuff,
sizeof(recvbuff), 0);
std::
string sendbuf = "hello, this is a Client…";
send(sockClient, sendbuf.c_str(), sendbuf.size(),
0);

//5. 关闭套接字
closesocket(sockClient);
WSACleanup();
return 0;
}

推荐阅读
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
author-avatar
夜冷
这个家伙很懒,什么也没留下!
RankList | 热门文章