基于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.收到消息在处理 ...
随机推荐
- mysql 刘道成视频教程 第3课
第3课: 1.mysql中条件使用关键字where: 2.查 select name,content from msg ; select name,content 控制列 where id>2 ...
- 设计模式之 Singleton 单例模式
先上两段代码,区别仅在于是否涉及线程安全. 首先是不涉及多线程的单例: public class Singleton { private final static Singleton INSTANCE ...
- APACHE 与IIS同时存在的情况下,给APACHE添加反向代理 共用80端口
一.首先打开IIS,将IIS的端口改成81,不要让IIS占用了80端口 二.打开APACHE的httpd.conf配置文件,将里面的端口配置成80 三.打开APACHE的虚拟目录配置文件,如:http ...
- Java之加密(信息摘要)工具类(依赖:java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils)
依赖于java.security.MessageDigest,支持MD5,SHA-1,SHA-256 import java.security.MessageDigest; import java.s ...
- 配置nginx支持thinkphp框架
因为nginx本身没有支持pathinfo,所以无法使用thinkphp框架,不过我们可以在配置里进行修改使其能够正常使用thinkphp. 1.修改配置支持pathinfo vi /etc/ngin ...
- 1.1机器学习基础-python深度机器学习
参考彭亮老师的视频教程:转载请注明出处及彭亮老师原创 视频教程: http://pan.baidu.com/s/1kVNe5EJ 1. 课程介绍 2. 机器学习 (Machine Learning, ...
- windows通过Composer安装yii2
1. php.ini 中;extension=php_openssl.dll(取消注释,不然在安装composer过程中会报错) 集成环境最好去php目录中打开php.ini文件,确定;extensi ...
- SpringMVC源码阅读(一)
DispatcherServlet是整个SpringMVC初始化和处理请求的重要类,作为一个servlet,拥有 public void init(ServletConfig config) thro ...
- 大话设计模式之策略模式(strategy)
策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响使用算法的用户. 针对商城收银模式,打折,返现促销等的例子: 打折还是促销其实都是一些算法,可以用工厂模式来 ...
- Codeforces Round #313 (Div. 2)
大半年没有打Codeforces , 昨天开始恢复打Codeforces, 简直是, 欲语泪先流啊. 手残到爆的写错了范围, 手残的数漏了条件, 简直不能直视, 最坑爹的是, E题没时间写代码了. 题 ...