bingbingc(网络编程TCP UDP)
Posted 月屯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bingbingc(网络编程TCP UDP)相关的知识,希望对你有一定的参考价值。
目录标题
字节序
- 小端字节序:低位放在低地址
- 大端字节序:低位放在高地址
- 主机字节序:指的是机器本身的字节序,如果是大端,则主机字节序为大端。如果是小端,则主机字节序为小端
- 网络字节序:规定网络传输数据的时候采用大端字节序进行传输
字节序转化
TCP和UDP
UDP socket编程
创建套接字的含义
将进程和网卡进行绑定,进程可以从网卡当中接收数据,也可以通过网卡发送数据
绑定地址信息的含义:
绑定ip,绑定端口,是为了在网络当中可以标识出来一台主机和一个进程。
- 对于接收方而言:发送数据的人就知道接收方在那台机器那个进程了
- 对于发送方而言:能标识网络数据从那台机器那个进程发送出去的
接口
netstat -anp |grep 28989// 端口占用情况
编码
客户端
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
using namespace std;
int main()
int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(sockfd<0)
perror("socker failed");
else
cout<<"socker "<<sockfd<<endl;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(28989);
addr.sin_addr.s_addr=inet_addr("172.17.0.1");//可私网或公网
const char* str="hello\\n";
sendto(sockfd,str,strlen(str),0,(struct sockaddr*)&addr,sizeof(addr));
close(sockfd);
return 0;
服务端
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(sockfd<0)
perror("socker failed");
else
cout<<"socker "<<sockfd<<endl;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(28989);
addr.sin_addr.s_addr=inet_addr("172.17.0.1");//必须是私网
int ret=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if(ret<0)
perror("bind failed");
char buf[1024]=0;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len=sizeof(cli_addr);
ssize_t recv_size=recvfrom(sockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&cli_addr,&cli_addr_len);
cout<<buf;
close(sockfd);
return 0;
完善
server
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
/*
* 1.创建套接字
* */
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sockfd < 0)
perror("socket");
return 0;
printf("sockfd is %d\\n", sockfd);
/*
* 2.绑定地址信息
* */
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(28989);
/*
* in_addr_t inet_addr(const char *cp);
* 1.将点分十进制的ip转化成为无符号的32位整数
* 2.将无符号32位整数转换成为网络字节序
* */
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
if(ret < 0)
perror("bind");
return 0;
while(1)
char buf[1024] = 0;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len = sizeof(cli_addr);
ssize_t recv_size = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&cli_addr, &cli_addr_len);
if(recv_size < 0)
return 0;
//ip:port client say:
printf("%s:%d client say:%s\\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
//发送数据
// hello, ip:port, i am server;
memset(buf, '0', sizeof(buf));
sprintf(buf, "hello, %s:%d, i am server~", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
sleep(1);
sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&cli_addr, sizeof(cli_addr));
close(sockfd);
return 0;
client
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
void UseAge()
printf("use command : ./udp_client [ip] [port]\\n");
int main(int argc, char* argv[])
/*
* ./udp_client ip port
* */
if(argc != 3)
UseAge();
return 0;
char* ip = argv[1];
uint16_t port = atoi(argv[2]);
/*
* 1.创建套接字
* */
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sockfd < 0)
perror("socket");
return 0;
printf("sockfd is %d\\n", sockfd);
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
/*
* in_addr_t inet_addr(const char *cp);
* 1.将点分十进制的ip转化成为无符号的32位整数
* 2.将无符号32位整数转换成为网络字节序
* */
dest_addr.sin_addr.s_addr = inet_addr(ip);
/*
* 2.发送数据
* */
while(1)
char buf[1024] = 0;
printf("cli# ");
fflush(stdout);
cin >> buf;
ssize_t send_size = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
if(send_size < 0)
return 0;
memset(buf, '\\0', sizeof(buf));
recvfrom(sockfd, buf, sizeof(buf) - 1, 0, NULL, NULL);
printf("%s\\n", buf);
close(sockfd);
return 0;
TCP
- 监听的含义:监听tcp客户端新的链接,同客户端建立tcp连接。注意:这个时候,TCP连接的建立在内核当中就完成了
- 获取新连接的含义:获取新连接的套接字描述符,每一个TCP连接会产生一个套接字描述符
- 发起连接的含义:向服务端发起TCP连接
接口
检查连接是否成功
成功无提示,失败提示失败
代码
单线程
客户端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>
using namespace std;
int main()
/*
* 1.创建侦听套接字
* 2.绑定
* 3.监听
* */
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
perror("listen_fd");
return 0;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(28989);
addr.sin_addr.s_addr = inet_addr("42.192.83.143");
int ret = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
if(ret < 0)
perror("connect");
return 0;
while(1)
char buf[1024] = 0;
cout << "please enter your msg# ";
fflush(stdout);
cin >> buf;
ssize_t send_size = send(sockfd, buf, strlen(buf), 0);
if(send_size < 0)
continue;
memset(buf, '\\0', sizeof(buf));
ssize_t recv_size = recv(sockfd, buf, sizeof(buf) - 1, 0);
if(recv_size < 0)
continue;
else if(recv_size == 0)
printf("server shutdown connect\\n");
break;
printf("%s\\n", buf);
close(sockfd);
return 0;
服务端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
/*
* 1.创建侦听套接字
* 2.绑定
* 3.监听
* */
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if(listen_fd < 0)
perror("listen_fd");
return 0;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(28989);
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
int ret = bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr));
if(ret < 0)
perror("bind");
return 0;
ret = listen(listen_fd, 5);
if(ret < 0)
perror("listen");
return 0;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len = sizeof(cli_addr);
int new_sockfd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cli_addr_len);
if(new_sockfd < 0)
perror("accept");
return 0;
while(1)
char buf[1024] = 0;
ssize_t recv_size = recv(new_sockfd, buf, sizeof(buf) - 1, 0);
if(recv_size < 0)
perror("recv");
continue;
else if(recv_size == 0)
printf("peer shutdown!!\\n");
close(new_sockfd);
return 0;
printf("buf is [%s]\\n", buf);
memset(buf, '\\0', sizeof(buf));
sprintf(buf, "[%s]:[%d], i am server, i recv your msg", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
send(new_sockfd, buf, strlen(buf), 0);
close(listen_fd);
return 0;
结论:单线程的程序,由于accept和recv都阻塞的特性,导致:
1.如果accept和recv都进行循环调用,会导致accept阻塞影响recv的接收,或者recv阻塞影响accept获取新连接,并且,accept接收回来的新连接套接字B会覆盖之前的新连接套接字A
多进程服务端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/wait.h>
#define Judge_ret(ret)if(ret < 0)return 0;
void sigcallback(int signum)
wait(NULLbingbingc(网络编程TCP UDP)