一、TCP编程的一般步骤

服务器端:

1、创建一个socket,用函数socket()

2、绑定IP地址、端口等信息到socket上,用函数bind()

3、开启监听,用函数listen()

4、接收客户端上来的连接,用函数accept()

5、收发数据,用函数send()和recv(),或者read()和write()

6、关闭网络连接

7、关闭监听

客户端:

1、创建一个socket,用函数socket()

2、设置要连接的对方IP地址和端口等属性

3、连接服务器,用函数connect()

4、收发数据,用函数send()和recv(),或者read()和write()

5、关闭网络连接

以下是TCP通信的时序图:

二、UDP编程的一般步骤

服务器:

1、创建一个socket,用函数socket()

2、绑定IP地址、端口等信息到socket上,用函数bind()

3、循环接收数据,用函数recvfrom()

4、关闭网络连接

客户端:

1、创建一个socket,用函数socket()

2、设置对方的IP地址、端口等属性

3、发送数据,用函数sendto()

4、关闭网络连接

以下是UDP通信的时序图:

三、Windows socket和Linux socket编程的区别

1、头文件

Windows下winsocket.h/winsocket2.h

Winsocket2.0需要ws2_32.lib和ws2_32.dll

Linux下sys/socket.h

错误处理:errno.h

2、初始化

Windows下需要WSAStartup

Linux不需要

3、关闭socket

Windows下closesocket

Linux下close

4、类型

Windows下SOCKET
Linux下int 
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif

#ifdef __Linux__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR (-1)
#endif

5、获取错误码

Windows下getlasterror()/WSAGetLastError()
Linux下errno变量

6、设置非阻塞

Windows下ioctlsocket()
Linux下fcntl() <fcntl.h>

7、send函数的最后一个参数

Windows下一般设置为0
Linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可 能会导致程序退出。

8、毫秒级时间获取

Windows下GetTickCount()
Linux下gettimeofday()

9、后续用到会再补充!!!

四、网络编程示例

1、Windows下TCP编程

服务器:

#include "stdafx.h"
#include <WinSock2.h>

#include <iostream>
using namespace std;
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
   
    WORD wVersionRequested = MAKEWORD(2,2);//确定最高可使用的socket版本
    WSADATA wsaData;//用来存储winsocket初始化信息

int err = WSAStartup(wVersionRequested, &wsaData);//初始化使用winsocket dll
    if (err != 0)
    {
        cout<<"WSAStartup failed!"<<endl;
    }

//步骤一:创建服务器socket
    //第一个参数选择协议族,第二个选择数据流类型,第三个选择协议类型
    SOCKET socketSrv = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (socketSrv == INVALID_SOCKET)
    {
        cout<<"Create socket failed"<<endl;
    }

//步骤二:绑定端口、IP信息到socket上
    SOCKADDR_IN addrSrv;  //这个结构用来存储本地端和远程端用来连接socket的信息
    //使用系统指定的IP地址。htonl将一个无符号长整形主机字节序转化为一个TCP/IP网络字节序(大端)
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(8888);//htons将一个无符号短整型端口主机字节序转化为一个TCP/IP网络字节序(大端)
    if (int n = bind(socketSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
    {
        cout<<"bind server socket failed"<<endl;
    }

//步骤三:监听
    if (listen(socketSrv,SOMAXCONN))//第二个参数为可接受的最大连接请求数
    {
        cout<<"listen failed"<<endl;
    }

//步骤四:接收客户端连接
    SOCKADDR_IN addrClient;//用来存放客户连接信息
    int nLen = sizeof(SOCKADDR);
    char buf1[255] = "";//存放连接的客户IP和端口信息字符串
    char buf2[255] = "";//接收和发送缓冲数据
    char bufRecv[255] = "";

//这个nlen没有设初值也会出错的哦
    SOCKET socketCon = accept(socketSrv,(SOCKADDR*)&addrClient,&nLen);//后面改成多线程后就能连接多人对话
    while (true)
    {
        //inet_ntoa将IPv4网络地址转换成标准的点治式字符串(例如:192.168.1.1)
        //ntohs将无符号短整型网络字节序转换为无符号短整型主机字节序,与上面的htons相反
        sprintf(buf1,"***IP:%s  PORT:%d #\n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port));

//步骤五:接收和传送数据
        int nBytesRecv = recv(socketCon,bufRecv,sizeof(bufRecv),0);
        if (strcmp(bufRecv,"exit") == 0)
        {
            //closesocket(socketCon);
            break;
        }
        strcat(buf1,bufRecv);
        cout<<buf1<<endl;
       
        cout<<"***YOU#:"<<endl;
        //cin>>buf2;
        cin.getline(buf2,sizeof(buf2));

int nBytesSent = send(socketCon,buf2,sizeof(buf1),0);

}
    //步骤六:关闭连接
    closesocket(socketCon);
    closesocket(socketSrv);
    WSACleanup();//终止使用winsocket dll

return 0;
}

客户端:

#include "stdafx.h"
#include <WinSock2.h>

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    WORD wVersionRequested = MAKEWORD(2,2);
    WSADATA wsaData;
    if (WSAStartup(wVersionRequested,&wsaData))
    {
        cout<<"WSAStartup failed"<<endl;
    }

//步骤一:创建socket
    SOCKET socktClient = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

//步骤二:设置要连接的对方的IP、端口等信息
    SOCKADDR_IN addrClient;
    //inet_addr将一个点制式IP字符串转换为适合IN_ADDR结构的形式
    addrClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrClient.sin_family = AF_INET;
    addrClient.sin_port = htons(8888);

//步骤三:连接服务器
    if (connect(socktClient,(SOCKADDR*)&addrClient,sizeof(SOCKADDR)))
    {
        cout<<"connect failed"<<endl;
    }

char buf[255] = "";

while (true)
    {
        //步骤四:收发数据
        cout<<"***YOU#"<<endl;
        //cin>>buf;
        cin.getline(buf,sizeof(buf));
        if (strcmp(buf,"exit") == 0)
        {
            break;
        }
        int nBytesSent = send(socktClient,buf,sizeof(buf),0);

int nBytesRecv = recv(socktClient,buf,sizeof(buf),0);
        cout<<"***Server#"<<endl;
        cout<<buf<<endl;
       
    }
    //步骤五:关闭连接
    closesocket(socktClient);
    return 0;
}

2、WIndows下UDP编程

服务器:

#include "stdafx.h"
#include <WinSock2.h>

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    WORD wVersionRequested = MAKEWORD(2,2);
    WSADATA wsaData;

WSAStartup(wVersionRequested,&wsaData);

//步骤一:创建socket
    SOCKET socketSrv = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//这里换成了非面向连接的数据报模式

SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(8000);

//步骤二:绑定端口、IP等信息到socket上
    if (bind(socketSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
    {
        cout<<"bind failed"<<endl;
    }

char buf[255] = "";
    while (true)
    {
        SOCKADDR_IN addrClient;//用来存放客户连接信息
        int nLen = sizeof(SOCKADDR);

//步骤三:接收数据
        int nBytesRecv = recvfrom(socketSrv,buf,sizeof(buf),0,(SOCKADDR*)&addrClient,&nLen);//这里不用变量存储会报错
        if (strcmp(buf,"exit") == 0)
        {
            //closesocket(addrClient);
            continue;
        }
        cout<<"Client#"<<endl;
        cout<<buf<<endl;

}

//步骤四:关闭网络连
    closesocket(socketSrv);
    WSACleanup();

return 0;
}

客户端:

#include "stdafx.h"
#include <WinSock2.h>

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    WORD wVersionRequested = MAKEWORD(2,2);
    WSADATA wsaData;

WSAStartup(wVersionRequested,&wsaData);

//步骤一:创建socket
    SOCKET socketClient = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//这里换成了非面向连接的数据报模式

//步骤二:设置要数据接收者的地址信息
    SOCKADDR_IN addrTo;
    addrTo.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrTo.sin_family = AF_INET;
    addrTo.sin_port = htons(8000);

char buf[255] = "";
    while (true)
    {
        cout<<"YOU#"<<endl;
        cin.getline(buf,sizeof(buf));
        if (strcmp(buf,"exit") == 0)
        {
            break;
        }

//步骤三:发送数据
        int nBytesSent = sendto(socketClient, buf,strlen(buf)+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
    }

//步骤四:关闭网络连
    closesocket(socketClient);
    WSACleanup();

return 0;
}

3、Linux下TCP编程

服务器:

客户端:

2、Linux下UDP编程

服务器:

客户端:

TCP/UDP网络编程的基础知识与基本示例(windows和Linux)的更多相关文章

  1. python六十七课——网络编程(基础知识了解)

    网络编程: 什么是网络编程? 网络:它是一种隐形的媒介:可以将多台计算机使用(将它们连接到一起) 网络编程:将多台计算机之间可以相互通信了(做数据交互) 一旦涉及到网络编程,划分为两个方向存在,一方我 ...

  2. java第九节 网络编程的基础知识

    /** * * 网络编程的基础知识 * 网络协议与TCP/IP * IP地址和Port(端口号) * 本地回路的IP地址:127.0.0.1 * 端口号的范围为0-65535之间,0-1023之间的端 ...

  3. 01网络编程(基础知识+OSI七层协议+TCP与UDP)

    目录 01 网络编程 一.软件开发架构 1.1 CS架构 1.2 BS架构 二.网络理论前戏 2.1 简介 2.2 常见硬件 三.OSI七层协议(五层) 3.1 七层协议 3.2 五层协议 3.3 知 ...

  4. TCP/IP网络编程技术基础

    零零碎碎记下点→ 不对的欢迎大家批评纠正→ 以免本人及偶尔看到此博客的人继续迷途未返→ >>>>>基础知识→ 1→TCP/IP英文名:Tranmission Contro ...

  5. 自测之Lesson15:TCP&UDP网络编程

    题目:编写一个TCP通信的程序. 实现代码: #include <stdio.h> #include <sys/socket.h> #include <unistd.h& ...

  6. 《TCP/IP网络编程》

    <TCP/IP网络编程> 基本信息 作者: (韩)尹圣雨 译者: 金国哲 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115358851 上架时间:2014-6- ...

  7. 【RL-TCPnet网络教程】第16章 UDP用户数据报协议基础知识

    第16章      UDP用户数据报协议基础知识 本章节为大家讲解UDP(User Datagram Protocol,用户数据报协议),需要大家对UDP有个基础的认识,方便后面章节UDP实战操作. ...

  8. 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

    这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...

  9. python网络编程——socket基础篇

    python的网络编程比c语言简单许多, 封装许多底层的实现细节, 方便程序员使用的同时, 也使程序员比较难了解一些底层的东西. 1 TCP/IP 要想理解socket,首先得熟悉一下TCP/IP协议 ...

随机推荐

  1. hdu5344 MZL's xor(水题)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud MZL's xor Time Limit: 2000/1000 MS (Java/ ...

  2. jquery 实现 隐藏交替同时记住以前隐藏的样式

    /* * control menu show or hide(expand and collapse) */ var status = []; function menuOperation() { $ ...

  3. Hibernate学习笔记(一):mycelipse建立项目流程(未完成)

    1.部署数据库: 2.部署项目: 3.引入Hibernate: 4.url配置

  4. 转载: js jquery 获取当前页面的url,获取frameset中指定的页面的url(有修改)

    转载网址:http://blog.csdn.net/bestlxm/article/details/6800077 js jquery 怎么获取当前页面的url,获取frameset中指定的页面的ur ...

  5. Number Sequence--hdu1005

    Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  6. 使用grid++report打印选中行

    接上一篇<hibernate+spring+mvc+Easyui框架模式下使用grid++report的总结>对grid++report做进一步开发 先写一下实现流程: 1.默认为全部载入 ...

  7. Idea使用记录--每次修改JS文件都需要重启Idea才能生效解决方法

    最近开始使用Idea,有些地方的确比eclipse方便.但是我发现工程每次修改JS或者是JSP页面后,并没有生效,每次修改都需要重启一次Tomcat这样的确不方便.我想Idea肯定有设置的方法,不可能 ...

  8. 【ROC曲线】关于ROC曲线、PR曲线对于不平衡样本的不敏感性分析说引发的思考

    ROC曲线 在网上有很多地方都有说ROC曲线对于正负样本比例不敏感,即正负样本比例的变化不会改变ROC曲线.但是对于PR曲线就不一样了.PR曲线会随着正负样本比例的变化而变化.但是没有一个有十分具体和 ...

  9. shell 脚本监控程序是否正在执行, 如果没有执行, 则自动启动该进程

    代码里面监控1个进程, 代码很简单, 我就不讲解了, 有不懂的, 可以在回复里面问. 我看见了会给予讲解. 当然了, 该脚本要执行,你需要开启系统的定时器进程 crond , 并且编辑配置文件. 执行 ...

  10. PagedList.MVC 应用

    1. NuGet 下载 PagedList.MVC 2. View Page @model PagedList.IPagedList<Libaray.Models.Entities.BookMo ...