基于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.收到消息在处理 ...
随机推荐
- Fedora 21 中添加及更新源的命令
原文: Fedora 21 中添加及更新源的命令 fedora的软件源信息文件(*.repo)都是放在 /etc/yum.repos.d 目录下的.可以通过# ls -l /etc/yum.repos ...
- Jquery常用功能
jQuery 1.4给开发者带来了很多值得兴奋的新特性,同时使用jQuery的人也越来越多,为了方便大家对jQuery的使用,下面列出了一些jQuery使用技巧.比如有禁止右键点击.隐藏搜索文本框文字 ...
- jsonp跨域问题记录
这段时间用H5做移动app开发,遇到不少之前做web的时候不曾遇到的问题,记录一下,共勉-- 首先说一个:js跨域取数的问题 描述: 之前做web都是通过后台获取数据,没考虑过跨域的问题.这次用h5 ...
- 简谈HashMap、HashTable的区别
简单的说HashMap是HashTable的轻量级实现,即非线程安全的实现,他们的主要区别概述为: HashMap HashTable (1)允许键和值为null 不允许键或值为null (2)不是 ...
- 通过jquery获取后台传过来的值进行全选
注:funs是从action中传过来的list<Function> 其中属性中有其子对象list<role> 下面通过s标签遍历 ,也可以通过c标签遍历 jsp页面中: < ...
- C#(MVC) Word 替换,填充表格,导出并下载PDF文档
近期做一个关于C# 操作 Word 模板 文档的功能模块,查阅资料,最终完美完成任务,记录下来,以便后面还会用到.
- Prefixes and Suffixes
Codeforces Round #246 (Div. 2) D:http://codeforces.com/contest/432/problem/D 题意:给你一个长度不超过10^5的字符串.要你 ...
- keil多文件组织方法
方法一 首先新建一个main.c的文件,加入到项目中,该文件中主要写main函数,然后,新建文件,如delay.c,编写内容之后,不要加入到项目,而是在main.c文件的开始写上#include“de ...
- Spark MLBase分布式机器学习系统入门:以MLlib实现Kmeans聚类算法
1.什么是MLBaseMLBase是Spark生态圈的一部分,专注于机器学习,包含三个组件:MLlib.MLI.ML Optimizer. ML Optimizer: This layer aims ...
- 2.5.3 使用alertDialog创建自定义对话框
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout ...