题目:编写一个TCP通信的程序。

实现代码:

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define PORT 0xaaaa // 服务端
void startServe()
{
int iRet; // socket()
int fd; // 文件描述符
fd = socket(PF_INET, SOCK_STREAM, 0); // 创建文件描述符,并确定是用TCP还是UDP等
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 即使目标地址不是我,只要发到该计算机上,我就能接收 iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); // 将文件描述符与本机地址绑定
if (iRet < 0) {
perror("fail bind");
close(fd); // 释放资源
return;
} // listen()
iRet = listen(fd, 5); // 最多监听5个连接请求
if (iRet < 0) {
perror("fail listen");
close(fd);
return;
}
printf("Server start OK, wait connect...\n"); // accept()
char szBuf[1024];
char szMsg[] = "Welcome...";
struct sockaddr_in clientAddr; // 客户端地址
socklen_t addrlen = sizeof(clientAddr);
while(1) {
int newFd; // 此newFd用于与客户端通信
newFd = accept(fd, (struct sockaddr*)&clientAddr, &addrlen);
if (newFd < 0) {
perror("fail accept");
break;
} char *pClientAddr = inet_ntoa(clientAddr.sin_addr); // 整数IP转字符串IP
int clientPort = ntohs(clientAddr.sin_port); // 网络字节序转主机字节序
printf("Connect from %s:%d\n", pClientAddr, clientPort);
memset(szBuf, 0, 1024);
iRet = read(newFd, szBuf, 1024);
if (iRet < 0) {
perror("fail read");
break;
}
printf("Recv:%s\n", szBuf);
write(newFd, szMsg, strlen(szMsg));
close(newFd); // 关闭当前accept创建的文件描述符
}
close(fd);
return;
} // 客户端
void startClient()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_STREAM, 0);
if(fd < 0) {
perror("fail socket");
return;
} // connect()
struct sockaddr_in srvAddr;
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr("192.168.85.128"); // 服务端的ip地址
srvAddr.sin_port = htons(PORT); // 服务端的端口号
iRet = connect(fd, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
if (iRet != 0) {
perror("fail connect");
return;
}
printf("Connect success\n");
fprintf(stderr, "Send:"); // read() & write()
char szBuf[1024];
memset(szBuf, 0, 1024);
read(STDIN_FILENO, szBuf, 1024); // 从标准输入 输入消息
write(fd, szBuf, strlen(szBuf));
char szRcv[1024]; memset(szRcv, 0, 1024);
read(fd, szRcv, 1024);
printf("[CLIENT]Rcv:%s\n", szRcv); close(fd);
return;
} int main(int argc, char **argv)
{
if (argc != 2 ||
(strcmp(argv[1], "s") && strcmp(argv[1], "c"))) {
printf("Usage: %s [ s | c ]\n", argv[0]);
printf("\ts: start server\n");
printf("\tc: start client\n");
return 0;
}
if (argv[1][0] == 's') {
startServe();
}
else if (argv[1][0] == 'c') {
startClient();
}
return 0;
} /* ReadMe */
/*
* 先启动服务端 --> ./a.out s
* 再启动客户端 --> ./a.out c
*/

题目:编写一个UDP通信的程序。

  

实现代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h> #define SRV_PORT 0xaaaa // 服务端 端口号
#define CLI_PORT 0xbbbb // 客户端 端口号
#define IP_ADDRESS "10.162.73.120" void startServer()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SRV_PORT);
iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet != 0) {
perror("fail bind");
return;
} // recvfrom() & sendto()
struct sockaddr_in cliAddr;
socklen_t addrLen = sizeof(cliAddr);
char szRcv[1024];
char szSnd[1024];
while(1) {
// recvfrom()
memset(szRcv, 0, 1024);
iRet = recvfrom(fd, szRcv, 1024, 0, (struct sockaddr*)&cliAddr, &addrLen);
if (iRet < 0) {
perror("fail recvfrom");
close(fd);
break;
}
char *pcliAddr = inet_ntoa(cliAddr.sin_addr);
int cliPort = ntohs(cliAddr.sin_port);
printf("Recv from client[%s:%d]\n", pcliAddr, cliPort);
printf("Recv:%s\n", szRcv); // sendto()
fprintf(stderr, "Send:");
memset(szSnd, 0, 1024);
read(STDIN_FILENO, szSnd, 1024);
iRet = sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&cliAddr, addrLen); }
close(fd);
} void startClient()
{
int iRet; // socket()
int fd;
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("fail socket");
return;
} // bind()
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(CLI_PORT);
iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet != 0) {
perror("fail bind");
return;
} // recvfrom() & sendto()
struct sockaddr_in srvAddr;
socklen_t addrLen = sizeof(srvAddr);
// 对端的地址信息,用于sendto()函数
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
srvAddr.sin_port = htons(SRV_PORT);
char szRcv[1024];
char szSnd[1024];
while(1) {
// sendto()
fprintf(stderr, "Send:");
memset(szSnd, 0, 1024);
read(STDIN_FILENO, szSnd, 1024);
sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&srvAddr, addrLen); // read()
memset(szRcv, 0, 1024);
read(fd, szRcv, 1024); // 上面的sendto()已经获得对端地址,此处可简写
printf("Recv:%s\n", szRcv);
}
close(fd);
} int main(int argc, char **argv)
{
if (argc != 2 ||
(strcmp(argv[1], "c") && strcmp(argv[1], "s")))
{
printf("Usage:%s [ s | c ]\n", argv[0]);
printf("\ts: start to server\n");
printf("\tc: start to client\n");
return 0;
}
if (argv[1][0] == 's') {
startServer();
}
else if (argv[1][0] == 'c') {
startClient();
}
return 0;
}

  

题目:编写一个抓包程序,要求抓取封装TCP报文段的包,并打印出包的头部信息。

实现代码:

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define PORT 0Xaaaa // 此端口仅用于bind(),而该程序可抓发送到任意端口的包 typedef struct _ipHeader {
// unsigned char ucVer:4;
// unsigned char ucHeadLen:4;
unsigned char ucVerHeadLen; // 不应该在此处用位域,可在后面提取位数
unsigned char ucTos;
unsigned short usLen;
unsigned short usIdent;
// unsigned short usFlag:3;
// unsigned short usOffset:13;
unsigned short usFlagOffset;
unsigned char ucTTL;
unsigned char ucProtocol;
unsigned short usChkSum;
// unsigned int uiSrcIp;
// unsigned int uiDestIp;
struct in_addr SrcIp;
struct in_addr DestIp;
char data[0];
} IP_HEADER; typedef struct _tcpHeader {
unsigned short SrcPort;
unsigned short DestPort;
unsigned int Seq;
unsigned int Ack;
// unsigned short HeadLen:4;
// unsigned short Save:6;
// unsigned short URG:1;
// unsigned short ACK:1;
// unsigned short PSH:1;
// unsigned short RST:1;
// unsigned short SYN:1;
// unsigned short FIN:1;
unsigned short HeadLenFlag; // 包括首部长度、保留、URG标志等字段
unsigned short Window;
unsigned short ChkSum;
unsigned short UrgPoint;
char data[0];
} TCP_HEADER; void printIpHeader(char szBuf[])
{
IP_HEADER *pHeader = (IP_HEADER*)szBuf;
printf("\n================IP HEADER================\n");
printf("\tVersion:%d\n", (pHeader->ucVerHeadLen) >> 4);
printf("\tHeadLen:%d\n", (pHeader->ucVerHeadLen) & 0x0f);
printf("\tSOUR IP:%s\n", inet_ntoa(pHeader->SrcIp));
printf("\tDEST IP:%s\n", inet_ntoa(pHeader->DestIp));
printf("=========================================\n");
} void printTcpHeader(char szBuf[])
{
TCP_HEADER *pHeader = (TCP_HEADER*)szBuf;
printf("\n===============TCP HEADER================\n");
printf("\tSOUR PORT:%d\n", ntohs(pHeader->SrcPort));
printf("\tDEST PORT:%d\n", ntohs(pHeader->DestPort));
printf("=========================================\n");
} void startCapturePacket()
{
int iRet; int fd;
fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP/* = NUM'6' */); // 抓取封装TCP报文段的IP数据报
if (fd < 0) {
perror("fail socket");
return;
} struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY); iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (iRet < 0) {
perror("fail bind");
close(fd);
return;
} char szBuf[1024];
while(1) {
memset(szBuf, 0, 1024);
read(fd, szBuf, 1024); // 将抓到的包整个存到szBuf中,此处szBuf的大小不是很合适
printIpHeader(szBuf); // 打印IP头部部分信息
printTcpHeader(szBuf); // 打印TCP报文端头部部分信息
}
close(fd);
return;
} int main()
{
startCapturePacket();
return 0;
}

  

自测之Lesson15:TCP&UDP网络编程的更多相关文章

  1. TCP/UDP网络编程的基础知识与基本示例(windows和Linux)

    一.TCP编程的一般步骤 服务器端: 1.创建一个socket,用函数socket() 2.绑定IP地址.端口等信息到socket上,用函数bind() 3.开启监听,用函数listen() 4.接收 ...

  2. JAVA UDP网络编程学习笔记

    一.UDP网络编程概述 采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的 ...

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

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

  4. 《TCP/IP网络编程》

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

  5. TCP/IP网络编程系列之四(初级)

    TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的 ...

  6. TCP/IP网络编程系列之三(初级)

    TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...

  7. TCP/IP网络编程之多播与广播

    多播 多播方式的数据传输是基于UDP完成的,因此,与UDP服务端/客户端的实现非常接近.区别在于,UDP数据传输以单一目标进行,而多播数据同时传递到加入(注册)特定组的大量主机.换言之,采用多播方式时 ...

  8. TCP/IP网络编程之套接字的多种可选项

    套接字可选项进而I/O缓冲大小 我们进行套接字编程时往往只关注数据通信,而忽略了套接字具有的不同特性.但是,理解这些特性并根据实际需要进行更改也十分重要.之前我们写的程序在创建好套接字后都是未经特别操 ...

  9. TCP/IP网络编程之基于TCP的服务端/客户端(一)

    理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流(stream)的套接字.TCP是Transmissi ...

随机推荐

  1. Vmware文件类型

    ### vmx ###> 虚拟机启动的配置文件+ 包含`.encoding`.`displayName`.`memsize`等基本配置信息,还包括一些链接文件的位置如`nvram`(非易变RAM ...

  2. 前端的字符串时间如何自动转换为后端Java的Date属性,介绍springMVC中如何解决时间转换问题

    平常在开发过程中,前端选择时间一般都要使用时间选择插件,但是这种插件选出来的时间都是字符串类型,我们该怎么转换为后端的Date呢?/? 前端效果如下(笔者用的是layDate5.0插件): 修改前的后 ...

  3. 前端String转json

    1.data = eval("("+data+")");2.JSON.parse(data);

  4. Redis学习笔记(一)

    定义 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库. 从该定义中抽出几个关键信息,以表示Redis的特性: 存储结构:key-val ...

  5. Centos7.5 lnmp+mongodb扩展

    安装NginxYUM源中没有Nginx,我们需要增加一个nginx的源nginx.repo # vi /etc/yum.repos.d/nginx.repo 源文件的内容 [nginx] name=n ...

  6. TCC : Tiny C Compiler (2018-2-6)

    饭墙下载,有缘上传: https://files.cnblogs.com/files/bhfdz/tcc-0.9.27-win32-bin.zip https://files.cnblogs.com/ ...

  7. 集合之HashMap、Hashtable

    HashMap 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Hashtabl ...

  8. H5测试(转载)

    可能有些朋友不明白啥是H5,但其实生活中我们经常会碰到. 比如,你经常收到的朋友虐狗第一式—结婚请贴. 你的朋友圈,可能会经常看到宝妈们虐狗第二式—晒可爱宝宝的相册. 你有可能也收到过这样,非常直观, ...

  9. pygame---制作一只会转弯的小乌龟

    Pygame Pygame是跨平台Python模块,专为电子游戏设计,包含图像.声音.建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚. 包含图像.声音. 建立在S ...

  10. 北京Uber优步司机奖励政策(1月14日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...