基于TCP的socket通信过程及例子
Socket也叫套接字,用来实现网络通讯,通过调用系统提供的API,可以和远程的机子传输数据。Socket有很多种协议,而这篇文章主要讨论TCP部分的内容,也就是说后面说的内容主要是指TCP Socket。
Socket 的一般调用过程:
服务端:socket(), bind(),listen(),accept(),send(),recv(),close()
客户端:socket(),connect(),send(),recv(),close()
阻塞socket(同步socket)
进程或线程执行到某些socket函数时必须等待该socket事件的发生,如果该事件没有发生,socket函数不能立即返回,进程或线程被阻塞。
特点:使用简单,适合一对一的应答场合,在服务端很少使用,或配合多线程使用
| 函数 | 返回值说明 | 阻塞情况 |
| accept() | 返回新的连接socket句柄。 | 缓冲区队列没有新的等待连接 |
| connect() | 返回-1说明连接失败,其他正常。 | 连接过程阻塞。 |
| recv() | 返回值小于1代表接收失败,其他代表接收数据的长度。 | 发送缓冲区有数据等待发送完成,或接收缓冲区没数据时阻塞。 |
| send() | 返回-1代表发送失败,其他为发送数据的长度 | 发送缓冲区没有足够空间保存此次发送数据时阻塞 |
非阻塞socket(异步socket)
进程或线程执行socket函数时不必非要等待该socket事件的发生,一旦执行立即返回。根据返回值的不同可以判断函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程可以不被阻塞,继续执行。
特点:函数执行立即返回,不会阻断进程,性能比阻塞高,适合在主线程直接调用,不会造成主线程卡顿现象
因为socket默认是阻塞的,所以要设置非阻塞模式:
#ifdef WIN32
DWORD nMode = 1;
ioctlsocket(m_sock, FIONBIO, &nMode);
#else
int r = fcntl(fd, F_GETFL, 0));
fcntl(fd, F_SETFL, r|O_NONBLOCK);
#endif
TCP与UDP 的区别
| 协议说明 | socket创建 | |
| TCP | 传输控制协议,可靠的连接服务。双方先建立连接再传输数据。提供超时重发,数据检验,流量控制等机制,保证数据发送无误。 | socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) |
| UDP | 用户数据报协议,不可靠的连接服务。没有建立连接就可以发送数据,没有超时重发机制,传输速度很快。 | socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) |
Socket例子
下面以一个简单例子来说明服务端与客户端的交互过程
服务端 server.cpp
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") #define PORT 8080 int main()
{
//初始化winsock服务
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData); //创建socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in svraddr;
svraddr.sin_family = AF_INET;
svraddr.sin_port = htons(PORT);
svraddr.sin_addr.s_addr = htonl(INADDR_ANY); //绑定socket
bind(sock, (struct sockaddr*)&svraddr, sizeof(svraddr)); //监听socket
listen(sock, 5); while(1)
{
struct sockaddr_in addr;
int len = sizeof(SOCKADDR); char buf[1024] = {0}; //接受客户端连接
SOCKET client = accept(sock, (struct sockaddr*)&addr, &len); char* ip = inet_ntoa(addr.sin_addr);
printf("accept client: %s\r\n", ip); //接收客户端数据
if(recv(client, buf, 1024, 0) >0)
{
printf("recv client: %s\r\n", buf); //向客户端发送数据
send(client, "hello, client", strlen("hello, client"), 0);
}
closesocket(client);
} //关闭socket
closesocket(sock); //关闭winsock服务
WSACleanup(); return 0;
}
客户端 client.cpp
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") #define REMOTE_IP "127.0.0.1"
#define REMOTE_PORT 8080 int main()
{
//初始化winsock服务
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData); //创建socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in svraddr;
svraddr.sin_family = AF_INET;
svraddr.sin_port = htons(REMOTE_PORT);
svraddr.sin_addr.s_addr = inet_addr(REMOTE_IP); //连接socket
if( connect(sock, (struct sockaddr*)&svraddr, sizeof(svraddr)) != -1)
{
//发送数据给服务端
if(send(sock, "hello, server", strlen("hello, server"), 0) != -1)
{
//接收服务端数据
char buf[1024] = {0};
if(recv(sock, buf, 1024, 0) >0)
{
printf("recv server: %s\r\n", buf);
} }
}
else
{
printf("can not connect server\r\n");
} //关闭socket
closesocket(sock); //关闭winsock服务
WSACleanup();
getchar();
return 0;
}
基于TCP的socket通信过程及例子的更多相关文章
- 基于TCP协议Socket通信
服务器线程处理类 package demo4; import java.io.*; import java.net.Socket; /** * 服务器线程处理类 * @ClassName Server ...
- IOS 基于TCP的socket通信详解(原创)
最近在整理通信层相关知识,这篇文章是边整理边写的,有些地方可能不够准确,还请各位路过的大牛专家指出来.这次整理的socket通信是基于TCP的,实现方式是GCD形式,以下记录的都是些理论知识,方便自己 ...
- 基于tcp的socket通信
# socket # socekt是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,socket其实就是一个门面模式,它 # 把复杂的tcp/ip协议族隐藏在socket接 ...
- python 之网络编程(基于TCP协议Socket通信的粘包问题及解决)
8.4 粘包问题 粘包问题发生的原因: 1.发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包),这样接收端,就难于分辨出来了,必须提供科学的拆包机制. ...
- 一个基于tcp的socket简单对话小例子
首先我们需要写连个py文件,一个server,一个client. import socket sk = socket.socket() # sk.bind(('ip',port)) sk.bind(( ...
- Java Web 基础(一) 基于TCP的Socket网络编程
一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...
- Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信
Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...
- 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接
本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...
- 事件驱动的TCP协议Socket通信
事件驱动的TCP协议Socket通信 介绍 常规的Socket通信案例一般都是在某个线程中建立连接,然后用一个while(true)循环判断是或否有数据传输,但是这种方法有局限性. 1.收到消息在处理 ...
随机推荐
- STUN/TURN/ICE协议在P2P SIP中的应用(二)
1 说明 2 打洞和穿越的概念... 1 3 P2P中的打洞和穿越... 2 4 使用STUN系列 协议穿越的特点... 2 5 STUN/ ...
- boost::xml——基本操作以及中文乱码解决方案 (续)
本博文主要想说明以下两点: 1.对于上一篇的<boost::xml——基本操作以及中文乱码解决方案>解释,这篇博文基本解决了正确输入输出中英文问题,但是好像还没有解决修改中文出现乱码的问题 ...
- JavaScript 输入自动完成插件
作为web开发的一员,应该都不陌生,信息处理时,很多时候需要根据用户的输入实时反馈查询结果供其选择,这给了用户很好的人机交互体验,在各大门户网站上已经被使用的很成熟了,最近项目中用到此功能,网上有很多 ...
- 零售POS开发
零售POS系统是一款基于离线与在线两种模式的POS系统,能够将门店的销售数据及时准确的同步到企业服务器.离线模式操作更加快捷.稳定.高效:在线操作实时同步会员信息.查看库存.下载最新档案.公文公告等一 ...
- jQuery提供的小方法
jQuery提供的小方法: 1.选择器 + 事件 + 函数 = 复杂的交互 2.循环处理与选择器匹配的各个元素:each() $("#").each(function(){ ...
- 求LR(0)文法的规范族集和ACTION表、GOTO表的构造算法
原理 数据结构 // GO private static Map<Map<Integer,String>,Integer> GO = new HashMap<Map< ...
- JavaScript学习心得(二)
一选择DOCTYPE DOCTYPE是一种标准通用标记语言的文档类型声明,目的是告诉标准通用标记语言解析器使用什么样的文档类型定义(DTD)来解析文档. 网页从DOCTYPE开始,即<!DOCT ...
- 【pyhton】短路逻辑
编程语言常用的逻辑if a and b:#如果a是false,那么跳过b的判断,结果直接falseif a or b:#如果a为true,那么跳过b的判断,直接true
- Python资源汇集
Python资源汇集 一 实用教程 廖雪峰网站 第一,Python教程:提供了循序渐进,重点是可操作的实用教程. 第二,Web App 项目教程.给出一个用16天完成的Python Web APP项目 ...
- 如何设置路由器实现静态IP配置
一.概述 嵌入式开发者,经常面对这样的环境:PC(windows)+虚拟机(linux)+开发板.我们希望三者都能相互通信,而且可以联网. 对于实验室只提供一根网线,而自己没有额外的增加端口数量的设备 ...