socket网络编程——TCP编程流程及端口号占用问题

29 篇文章 3 订阅
订阅专栏
9 篇文章 0 订阅
订阅专栏

1.TCP编程流程

1.1TCP服务器端客户端及方法介绍

TCP 提供的是面向连接的、可靠的、字节流服务。TCP 的服务器端和客户端编程流程如下:
在这里插入图片描述
socket()方法是用来创建一个套接字,有了套接字就可以通过网络进行数据的收发。这也是为什么进行网络通信的程序首先要创建一个套接字。创建套接字时要指定使用的服务类型,使用 TCP 协议选择流式服务(SOCK_STREAM)。
bind()方法是用来指定套接字使用的 IP 地址和端口。IP 地址就是自己主机的地址,如果主机没有接入网络,测试程序时可以使用回环地址“127.0.0.1”。端口是一个 16 位的整形值,一般 0-1024 为知名端口,如 HTTP 使用的 80 号端口。这类端口一般用户不能随便使用。其次,1024-4096 为保留端口,用户一般也不使用。4096 以上为临时端口,用户可以使用。在Linux 上,1024 以内的端口号,只有 root 用户可以使用。
listen()方法是用来创建监听队列。监听队列有两种,一个是存放未完成三次握手的连接,一种是存放已完成三次握手的连接。listen()第二个参数就是指定已完成三次握手队列的长度。
accept()方法处理存放在 listen 创建的已完成三次握手的队列中的连接。每处理一个连接,则accept()返回该连接对应的套接字描述符。如果该队列为空,则 accept 阻塞。
connect()方法一般由客户端程序执行,需要指定连接的服务器端的 IP 地址和端口。该方法执行后,会进行三次握手,建立连接。
在这里插入图片描述
send()方法用来向 TCP 连接的对端发送数据。send()执行成功,只能说明将数据成功写入到发送端的发送缓冲区中,并不能说明数据已经发送到了对端。send()的返回值为实际写入
到发送缓冲区中的数据长度。
recv()方法用来接收 TCP 连接的对端发送来的数据。recv()从本端的接收缓冲区中读取数据,如果接收缓冲区中没有数据,则 recv()方法会阻塞。返回值是实际读到的字节数,如果
recv()返回值为 0, 说明对方已经关闭了 TCP 连接。
close()方法用来关闭 TCP 连接。此时,会进行四次挥手。
在这里插入图片描述

1.2服务端客服端示例代码

TCP服务端代码示例(方法参数意思参考 套接字地址结构和 网络编程接口):

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);//将短整形主机字节转换为网络字节
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//回环地址

    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    assert(res != -1);

    res = listen(sockfd,5);
    assert(res != -1);

    while(1)//服务器循环接收客户端连接
    {
        struct sockaddr_in caddr;
        int len = sizeof(caddr);
        int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
        if(c == -1)
        {
            perror("accept error");
            continue;
        }

        printf("accept c = %d\n",c);
        char data[128];
        int n = recv(c,data,127,0);//阻塞
        printf("n = %d,buff = %s\n",n,data);

        send(c,"OK",2,0);

        close(c);

    }
    close(sockfd);
    exit(0);

}

TCP客户端代码示例

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);

    struct sockaddr_in saddr;
    saddr.sin_port = htons(6000);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    assert(res != -1);

    printf("please input:");
    fflush(stdout);
    char buff[128] = {0};
    fgets(buff,127,stdin);

    send(sockfd,buff,strlen(buff),0);

    char data[128] = {0};
    int n = recv(sockfd,data,127,0);
    printf("%s\n",data);
    close(sockfd);
    exit(0);


}

运行结果(服务端):
在这里插入图片描述
客户端:
在这里插入图片描述

客户端循环发送示例代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    assert(res != -1);
    
    while(1)
    {
        char buff[128] = {0};
        printf("input:\n");
        fgets(buff,127,stdin);
        if(strncmp(buff,"end",3) == 0)
        {
            break;
        }
        send(sockfd,buff,strlen(buff),0);
        memset(buff,0,128);
        recv(sockfd,buff,127,0);
        printf("buff = %s\n",buff);
    }
    close(sockfd);
}

2.端口号占用问题

当我们执行完服务端客户端代码后,再次执行客户端的时候发现执行不起来:
在这里插入图片描述
这个assert断言是下图这个地方出现问题。
在这里插入图片描述
这是怎么回事呢?
这是因为我们对上次服务端执行后,端口还没来得及释放,6000这个端口仍然被占用着。我们可以用命令netstat -anp | grep +端口号或者netstat -tunlp | grep + 端口号查看这个端口被哪个进程占用着。注意:LISTEN才表示正在被占用
在这里插入图片描述
在这里插入图片描述
也可以使用netstat -nultp命令查看当前所有已经使用的端口的情况。

在这里插入图片描述

网络通信,IP地址, 端口socket
moonlightpeng的博客
05-23 7281
目录 1. 什么是网络 2. 使用网络的目的 ip地址 1. 什么是地址 2. ip地址的作用 查看或配置网卡信息:ifconfig 测试远程主机连通性:ping 3. ip地址的分类(了解) 端口 1. 什么是端口 2. 端口号 3. 端口是怎样分配的 4. 小总结 socket简介 1. 不同电脑上的进程之间如何通信 2. 什么是socket 3.创建soc...
socket调试工具,可以启动服务端绑定特定的ip端口,也可以使用服务端连接特定ip端口发送数据
06-13
socket调试工具,可以启动服务端绑定特定的ip端口发送数据给客户端,也可以使用服务端连接特定ip端口发送数据给服务端,可以随时断开更改功能,
解决socket service端口占用问题
laocui1的博客
04-06 930
这样,即使上一个服务还没有完全关闭,也可以在相同端口上启动另一个服务。在创建socket service后加入如下设置。
TCP通讯指定客户端接收数据的端口(Socket)
一生挚爱妹子的博客
11-16 9985
使用Socket实现TCP通讯时,服务端响应数据给客户端时,客户端接收数据的端口是随机的。如果想指定客户端接收数据的端口,那么可以在客户端创建Socket时使用如下API: socket = new Socket(ip, serverPort, InetAddress.getByName(getLocalIpAddress()),clientPort); getLocalIpAddress(...
Socket、描述符、端口号
m0_58699417的博客
01-04 1343
Socket、描述符、端口号
Socket——端口
qyqingyan的专栏
10-25 3023
端口: 在客户端每一个TCP连接都会分配一个端口端口号的范围为0 到65535 ,其中0 到1023 的端口号一般固定分配给一些服务。 例如, 21 端口分配给FTP 服务, 25 端口分配给SMTP (简单邮件传输〉服务, 80 端 口分配给HTTP(超级文本传输〉服务, 135 端口分配给RPC (远程过程调用〉服务等。 从1024 到65535
检测tcp端口是否被占用
09-04
程序检测某个端口是否被tcp占用,vs2010测试通过。
TCPView端口查看,win的进程查看器,可以查看运行程序的端口占用
02-20
TCPView端口查看,win的进程查看器,可以查看运行程序的端口占用
端口占用查询工具(windows)
02-21
端口占用查询工具(windows),查询端口占用TCPView is a Windows program that will show you detailed listings of all TCP and UDP endpoints on your system, including the local and remote addresses and ...
TCPView-查看端口号.zip
07-07
TCP端口非常好用的查看工具,界面友好。通过此工具,可以详细的看到当前计算机进程中使用了哪些IP地址/端口,对于查找进程IP端口占用端口冲突等很有用,也可以结合防火墙使用。
Linux中解除端口占用的方法
01-10
在本例中,假设8080端口占用。 1.查看8080端口是否被占用 netstat -anp | grep 8080 输出结果:tcp 0 0 :::8080 :::* LISTEN 3000/java 由上可知8080端口已经被开启。 2.查看占用8080端口的进程: fuser -v -n ...
关于TCPSocket端口使用的一些理解
好好学习
05-05 2136
最近在复习计算机网络上的一些知识,产生了几点困惑。 首先是一道面试题,之前蚂蚁金服的面试官问到的:服务器突然崩溃了,然后重启服务器的时候80端口占用了,什么原因,提示我与四次挥手有关。 之前看四次挥手的时候,有说到服务器上会有大量的time_wait浪费资源,就想到一个问题:服务器是上层是使用Http协议传输数据的。那么使用http协议传输数据的时候,谁先主动断开TCP连接呢?(只有主动断开的...
socket重启 端口占用
小林码事
08-02 4885
问题描述: 代码是linux上一个socket服务器端,客户端与其建立连接;Ctrl+c 结束socket服务器。再次重启服务器后,端口占用,bind失败(Address already in use);需经过大约2分钟后,重启服务器方能再次使用。 问题分析: 因为socket结束后,linux会保留此端口一定时间,据说是1~4分钟;过后才能再次被使用。 处理方法: 设置SO_REUS...
C++ Socket 端口占用解决方法
weixin_34265814的博客
10-10 1217
2019独角兽企业重金招聘Python工程师标准>>> ...
创建socket项目提示端口号被使用的解决方法
XYY_2001的博客
10-06 464
创建socket数据报套接字udp项目时,服务端程序不恰当关闭后,再次启动会提示错误:Exception in thread "main" java.net.BindException: Address already in use: Cannot bind,显示地址已经被占用。在其中查找关键的UDP和9090 ,记录其中对应的pid为15656。点击pid排序,在其中查找对应的任务,点击结束任务即可。源代码中假设端口号port为9090。打开电脑的任务管理器,点击详细信息。
[转] 解决socket端口占用问题
mjm0771的专栏
02-15 9651
<br />这段时间遇到一个棘手的问题。现象如下:<br />VC6工程,程序a.exe使用TCPSocket通讯。但当程序a.exe结束后,通讯中绑定的端口会始终处于监听状态,外部地址是0.0.0.0,所属的进程PID是已经结束了的a.exe原有的PID。已经确认,a.exe在结束前已经成功调用closesocket()关闭了socket,并调用了WSAClean()。但端口依旧被占用,处于LISTENING状态。<br />经过长时间研究发现,问题是由于创建子进程导致的。a.exe中会通过Create
Socket编程之-------查询正在使用的端口号??
wodwl的专栏
08-04 3163
以下代码可以用来查询1023端口号及以下的占用情况: package com.wodwl.example;import java.io.IOException;import java.net.ServerSocket; public class ScanLocal { public static void main(String[] args) {  for (int i =
HCIP-Datacom-ARST自选题库__BGP/MPLS IP VPN简答【3道题】
最新发布
2301_80961833的博客
05-29 147
RD。
基于iptables 实现 ip 黑名单、白名单
nextvary的博客
05-23 265
基于iptables 实现 ip 黑名单、白名单
_linux下C++ socket网络编程——即时通信系统(含源码)
05-29
很高兴能够回答你的问题。以下是一个简单的即时通信系统的C++网络编程示例,基于Linux平台使用socket库进行开发。 客户端代码: ```c++ #include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> using namespace std; int main() { // 创建socket int client_socket = socket(AF_INET, SOCK_STREAM, 0); // 配置服务器地址 sockaddr_in server_address{}; server_address.sin_family = AF_INET; server_address.sin_port = htons(8080); server_address.sin_addr.s_addr = inet_addr("127.0.0.1"); // 连接服务器 int connect_result = connect(client_socket, (sockaddr *) &server_address, sizeof(server_address)); if (connect_result == -1) { cout << "连接服务器失败!" << endl; return -1; } // 发送消息 char message[1024] = {0}; while (true) { cin.getline(message, sizeof(message)); if (strlen(message) == 0) { continue; } send(client_socket, message, strlen(message), 0); memset(message, 0, sizeof(message)); } // 关闭socket close(client_socket); return 0; } ``` 服务器端代码: ```c++ #include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> using namespace std; int main() { // 创建socket int server_socket = socket(AF_INET, SOCK_STREAM, 0); // 配置服务器地址 sockaddr_in server_address{}; server_address.sin_family = AF_INET; server_address.sin_port = htons(8080); server_address.sin_addr.s_addr = inet_addr("127.0.0.1"); // 绑定socket和地址 bind(server_socket, (sockaddr *) &server_address, sizeof(server_address)); // 监听客户端连接 listen(server_socket, 10); // 接受客户端连接 sockaddr_in client_address{}; socklen_t client_address_len = sizeof(client_address); int client_socket = accept(server_socket, (sockaddr *) &client_address, &client_address_len); // 接收消息 char message[1024] = {0}; while (true) { int recv_result = recv(client_socket, message, sizeof(message), 0); if (recv_result <= 0) { break; } cout << "收到消息:" << message << endl; memset(message, 0, sizeof(message)); } // 关闭socket close(client_socket); close(server_socket); return 0; } ``` 在上面的代码中,客户端和服务器端都使用了socket库中的函数来完成网络通信。客户端使用`socket`函数创建socket,使用`connect`函数连接服务器,并使用`send`函数发送消息。服务器端使用`socket`函数创建socket,使用`bind`函数将socket与服务器地址绑定,使用`listen`函数监听客户端连接,并使用`accept`函数接受客户端连接,最后使用`recv`函数接收客户端发送的消息。 当然,这只是一个简单的示例。在实际开发中,你需要考虑更多的细节,例如如何处理多个客户端连接、如何处理异常情况等等。 希望这个示例能够帮助你了解Linux下C++ socket网络编程的基本流程和方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • C语言——逗号表达式 18411
  • Linux线程——线程创建和基本使用(多线程并发) 13635
  • 计算机操作系统——页面置换算法 12796
  • 父类指针指向子类对象的问题、父类对象和子类对象之间的问题 9925
  • C++四种类型强制转换——const_cast、static_cast、dynamic_cast、reinterpret_cast 9826

分类专栏

  • 数据结构和算法 25篇
  • C++ 25篇
  • 音视频学习记录 2篇
  • Qt 2篇
  • C语言 11篇
  • 实战练习
  • 计算机系统 4篇
  • 设计模式 9篇
  • 脚本语言 11篇
  • Linux操作系统 29篇
  • 计算机网络 9篇
  • 数据库

最新评论

  • 排序算法——拓扑排序(卡恩算法(广度优先)、dfs+深度搜索算法)

    Yoda1122: 为什么这么写落谷的家谱树过不了

  • C++中虚继承产生的虚基类指针和虚基类表,虚函数产生的虚函数指针和虚函数表

    子饺: 明白了,多谢表情包

  • C++中虚继承产生的虚基类指针和虚基类表,虚函数产生的虚函数指针和虚函数表

    2301_78958433: child_addr=&this->vbtable+this->vbtable[count]计算出来的,vbtable[0]是OffsetOf(class.vbtable)的相反数

  • C++中虚继承产生的虚基类指针和虚基类表,虚函数产生的虚函数指针和虚函数表

    2301_78958433: vbtable上面有vtable所以对象指针相对于vbtable的指针偏移为-4

  • 友元的创建和使用(普通函数做友元,成员函数做友元,类做友元)

    Gilgamesh_02: 感谢,成员函数做友元原来是要把定义放到另一个类定义下面写表情包

大家在看

  • 2024年延安市企业技术中心奖补政策及申报认定条件流程
  • Java开发-特殊文本文件,日志技术 563
  • Nginx使用(一) — Nginx搭建负载均衡(ubuntu-22.04.2-live-server环境) 1
  • 1598. Crawler Log Folder
  • 爬虫爬取电影,下载ts并合并ts实例

最新文章

  • 音频——多声道Plane格式处理(音频基本知识、音频多声道Plane格式等)
  • Qt之初学者遇坑杂谈
  • define趣谈——“#define false true“ 和 “#define true false“
2022年6篇
2021年113篇

目录

目录

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳SEO优化公司佛山网站改版报价曲靖网站关键词优化价格福田网站推广方案报价郑州推广网站多少钱布吉优秀网站设计报价广州外贸网站制作公司迪庆网站建设设计推荐山南网站seo优化公司泰安网站优化软件报价盐城网络推广哪家好芜湖企业网站改版推荐株洲百度网站优化排名哪家好芜湖seo优化威海网站优化按天扣费公司垦利网页设计哪家好迪庆网站开发报价同乐企业网站改版推荐布吉网站推广系统哪家好新余营销网站哪家好黄山seo济南网站排名优化公司迁安企业网站建设多少钱塔城设计公司网站多少钱株洲网络营销推荐酒泉网络推广公司枣庄网页设计松岗网站优化按天计费价格西乡SEO按效果付费哪家好辽源网站定制哪家好张北优化歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化