TCP服务器、客户端的简单实现
2017-08-06 23:24
507 查看
1. IP地址(IPV4 IPV6)
以一个32位的整形表示:172.166.111.110 -》点分10进程
地址 255.255.255.255
表示为 FF FF FF FF ->二进程
2.IP地址分类
A类地址:0.0.0.0 -- 127.255.255.255
网络号 + 主机号 网络号高(0-7) 主机号低(8—31)
B类地址:128.0.0.0 -- 191.255.255.255 网络号高(0-15) 主机号低(16-31)
C类地址: 192.0.0.0 -- 223.255.255.255 网络号高(0-23) 主机号低(24-31)
D类地址:224.0.0.0 -- 239.255.255.255 用来做组播网络
E类地址:240.0.0.0 -- 255.255.255.255 用来做广播网络
说明:网络号 -》识别是那个网络
主机号 -》识别是那一台PC
192.168.7.6 ---》 C类地址 网络通信时必须要地址段相同
192.168.6.6 ---》 C类地址
3.端口号 -》识别主机中的哪一个进程
IP地址:识别网络中的那一套主机,端口号就是用来识别,当前主机中的哪一个进程
端口号的取值范围:1-65535
在使用端口号时要注意:一般使用1000以后的端口号,因为1000以前的端口号,一般被系统进程占用着
-----------------------------------------------------------------------------------------------------
传输层协议:
TCP协议 UDP协议
TCP协议可靠传输协议:一般用于文件传输,与控制命令传输。
UDP协议不可传输协议:一般用于多媒体体数据传输,例如音频,视屏
TCP协议的搭建流程:
-----------------------------客户端-----------------------------------
1.创建socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int socket(int domain, int type, int protocol);
参数一:IP协议 AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
参数二:传输协议 SOCK_STREAM ---》TCP协议
SOCK_DGRAM ---》UDP协议
参数三:socket的属性 填写为0 默认属性
返回值:成功发回 新的socket文件描述符 ,失败返回 -1
2.链接服务器 connect (难点!!!!!!!!重点!!!)
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数一:socket文件描述符
参数二:服务器信息结构体
参数三:服务器信息结构体的大小
返回值:链接成功返回0 链接失败返回-1
const struct sockaddr *addr 服务器信息结构体 他的所在路径为 /usr/include/linux/in.h
struct sockaddr 与 struct sockaddr_in 在使用上是等价的。
struct sockaddr_in结构体介绍:
struct sockaddr_in {
__kernel_sa_family_t sin_family;
/* Address family协议族 IPV4 还是IPV6协议*/
__be16 sin_port;
/* Port number端口号*/
struct in_addr sin_addr;
/* Internet addressIP地址*/
}
/* Internet address. */IP地址结构体
struct in_addr {
__be32
s_addr;
};
IP地址转换函数:
#include <sys/socket.h>
#include <netinet/in.h> -》会与linux/in.h冲突,所以在加入点分10进制转换函数后要把原来那个头文件去掉
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp); -》点分10进制转整形
char *inet_ntoa(struct in_addr in); -》整形转点分10进制类型
大小端格式:在网络通信中都使用大端格式进行通信(所以我们需要转换端口号)
大端格式:低地址存储高位字节
小段格式:低地址存储低位字节
uint16_t htons(uint16_t hostshort); -》主机序转网络序
uint16_t ntohs(uint16_t netshort); -》网络序转主机序
--------------------------------服务器端----------------------------------------
1.创建socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int socket(int domain, int type, int protocol);
参数一:IP协议 AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
参数二:传输协议 SOCK_STREAM ->TCP协议
SOCK_DGRAM -》UDP协议
参数三:socket的属性 填写为0 默认属性
返回值:成功发回 新的socket文件描述符 ,失败返回 -1
2.绑定socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数一:创建的socket文件描述符
参数二:服务器绑定信息
参数三:服务器信息结构体的大小
返回值:成功返回0 ,失败返回-1
3.设置为监听socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int listen(int sockfd, int backlog);
参数一:创建的socket文件描述符
参数二:最大监听数 (同时可以接受多少个客户端的链接请求)
返回值:成功返回0 失败返回-1.
4.链接服务器 (重点!!!) 他会阻塞等待客户端链接过来
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数一:监听的文件描述符
参数二:客户端的信息结构体(例如客户端的IP,端口号)
参数三:成功接受客户端的信息结构体大小
返回值:接受链接请求成功,返回一个新的文件描述符,失败返回-1
--------------------------------------------------------------------------------------------------------------------------------------
练习:tcp服务器和客户端的简单通信实现
【server.c】
----------------------------------------------------------------------------------------------------------------------------------------------
【client.c】
-----------------------------------------------------------------------------------------------------------
程序运行时必须先运行服务器程序,再运行客户端程序,并且设置端口和服务器ip地址
![](https://img-blog.csdn.net/20170806232248516)
以一个32位的整形表示:172.166.111.110 -》点分10进程
地址 255.255.255.255
表示为 FF FF FF FF ->二进程
2.IP地址分类
A类地址:0.0.0.0 -- 127.255.255.255
网络号 + 主机号 网络号高(0-7) 主机号低(8—31)
B类地址:128.0.0.0 -- 191.255.255.255 网络号高(0-15) 主机号低(16-31)
C类地址: 192.0.0.0 -- 223.255.255.255 网络号高(0-23) 主机号低(24-31)
D类地址:224.0.0.0 -- 239.255.255.255 用来做组播网络
E类地址:240.0.0.0 -- 255.255.255.255 用来做广播网络
说明:网络号 -》识别是那个网络
主机号 -》识别是那一台PC
192.168.7.6 ---》 C类地址 网络通信时必须要地址段相同
192.168.6.6 ---》 C类地址
3.端口号 -》识别主机中的哪一个进程
IP地址:识别网络中的那一套主机,端口号就是用来识别,当前主机中的哪一个进程
端口号的取值范围:1-65535
在使用端口号时要注意:一般使用1000以后的端口号,因为1000以前的端口号,一般被系统进程占用着
-----------------------------------------------------------------------------------------------------
传输层协议:
TCP协议 UDP协议
TCP协议可靠传输协议:一般用于文件传输,与控制命令传输。
UDP协议不可传输协议:一般用于多媒体体数据传输,例如音频,视屏
TCP协议的搭建流程:
-----------------------------客户端-----------------------------------
1.创建socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int socket(int domain, int type, int protocol);
参数一:IP协议 AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
参数二:传输协议 SOCK_STREAM ---》TCP协议
SOCK_DGRAM ---》UDP协议
参数三:socket的属性 填写为0 默认属性
返回值:成功发回 新的socket文件描述符 ,失败返回 -1
2.链接服务器 connect (难点!!!!!!!!重点!!!)
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数一:socket文件描述符
参数二:服务器信息结构体
参数三:服务器信息结构体的大小
返回值:链接成功返回0 链接失败返回-1
const struct sockaddr *addr 服务器信息结构体 他的所在路径为 /usr/include/linux/in.h
struct sockaddr 与 struct sockaddr_in 在使用上是等价的。
struct sockaddr_in结构体介绍:
struct sockaddr_in {
__kernel_sa_family_t sin_family;
/* Address family协议族 IPV4 还是IPV6协议*/
__be16 sin_port;
/* Port number端口号*/
struct in_addr sin_addr;
/* Internet addressIP地址*/
}
/* Internet address. */IP地址结构体
struct in_addr {
__be32
s_addr;
};
IP地址转换函数:
#include <sys/socket.h>
#include <netinet/in.h> -》会与linux/in.h冲突,所以在加入点分10进制转换函数后要把原来那个头文件去掉
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp); -》点分10进制转整形
char *inet_ntoa(struct in_addr in); -》整形转点分10进制类型
大小端格式:在网络通信中都使用大端格式进行通信(所以我们需要转换端口号)
大端格式:低地址存储高位字节
小段格式:低地址存储低位字节
uint16_t htons(uint16_t hostshort); -》主机序转网络序
uint16_t ntohs(uint16_t netshort); -》网络序转主机序
--------------------------------服务器端----------------------------------------
1.创建socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int socket(int domain, int type, int protocol);
参数一:IP协议 AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
参数二:传输协议 SOCK_STREAM ->TCP协议
SOCK_DGRAM -》UDP协议
参数三:socket的属性 填写为0 默认属性
返回值:成功发回 新的socket文件描述符 ,失败返回 -1
2.绑定socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数一:创建的socket文件描述符
参数二:服务器绑定信息
参数三:服务器信息结构体的大小
返回值:成功返回0 ,失败返回-1
3.设置为监听socket
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int listen(int sockfd, int backlog);
参数一:创建的socket文件描述符
参数二:最大监听数 (同时可以接受多少个客户端的链接请求)
返回值:成功返回0 失败返回-1.
4.链接服务器 (重点!!!) 他会阻塞等待客户端链接过来
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数一:监听的文件描述符
参数二:客户端的信息结构体(例如客户端的IP,端口号)
参数三:成功接受客户端的信息结构体大小
返回值:接受链接请求成功,返回一个新的文件描述符,失败返回-1
--------------------------------------------------------------------------------------------------------------------------------------
练习:tcp服务器和客户端的简单通信实现
【server.c】
#include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> //写操作 void *write_fun(void *arg) { int fd=*(int *)arg; char buf[50]={0}; //输入指令 while(1) { scanf("%s",buf); write(fd,buf,strlen(buf)); } } //读操作 void *read_fun(void *arg) { int fd=*(int *)arg; char buf[50]={0}; //输入指令 while(1) { bzero(buf,50); read(fd,buf,50); printf("buf=%s\n",buf); } } int main(int argv,char **argc) { if(argv<3) { perror("plese input ./server prot ip"); return 0; } //1.创建TCP socket int sockfd=socket( AF_INET,SOCK_STREAM ,0); if(sockfd<0) { perror("create sock fail\n"); } else { printf("create sock %d\n",sockfd); } //设置服务器绑定信息 struct sockaddr_in serveraddr; bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family = AF_INET ; //IPV4协议 serveraddr.sin_port = htons(atoi(argc[1])); //端口号 serveraddr.sin_addr.s_addr = inet_addr(argc[2]);//IP地址 "0.0.0.0" ->万用地址 // htonl(INADDR_ANY) //INADDR_ANY ->万用IP宏 //2.绑定服务器 int ret=bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); if(ret != 0) { perror("bind fail\n"); } else { printf("bind ok\n"); } //3.设置为监听socket ret=listen(sockfd,5); if(ret != 0) { perror("listen fail\n"); } else { printf("listen ok\n"); } //定义一个结构体保存客户端的信息 struct sockaddr_in clienaddr; bzero(&clienaddr,sizeof(clienaddr)); //定义一个整形保存接收的长度 socklen_t len=sizeof(clienaddr); //4.接收客户端的链接请求(重点!!!) while(1) { int newfd=accept(sockfd,(struct sockaddr *)&clienaddr,&len); if(newfd>0) { printf("accept OK fd=%d\n",newfd); printf("clien ip=%s,port=%d\n",inet_ntoa(clienaddr.sin_addr),ntohs(clienaddr.sin_port)); //写入信息携程 pthread_t pid; pthread_create(&pid,NULL,write_fun,(void *)&newfd); //读取信息线程 pthread_t pid1; pthread_create(&pid1,NULL,read_fun,(void *)&newfd); } else { perror("accept fail\n"); } } }
----------------------------------------------------------------------------------------------------------------------------------------------
【client.c】
#include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> void *write_fun(void *arg) { int fd=*(int *)arg; char buf[50]={0}; //输入指令 while(1) { scanf("%s",buf); write(fd,buf,strlen(buf)); } } int main(int argv,char **argc) { if(argv<3) { perror("plese input ./clien prot ip"); return 0; } //创建TCP socket int sockfd=socket( AF_INET,SOCK_STREAM ,0); if(sockfd<0) { perror("create sock fail\n"); } else { printf("create sock %d\n",sockfd); } //设置服务器信息 struct sockaddr_in serveraddr; bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family = AF_INET ; //IPV4协议 serveraddr.sin_port = htons(atoi(argc[1])); //端口号 serveraddr.sin_addr.s_addr = inet_addr(argc[2]);//IP地址 //进行读写操作 char buf[50]={0}; //链接服务器 int ret=connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); if(ret != 0) { perror("connect fail\n"); } else { //使用一个写入线程 pthread_t pid; pthread_create(&pid,NULL,write_fun,(void *)&sockfd); while(1) { bzero(buf,sizeof(buf)); ret=read(sockfd,buf,sizeof(buf)); if(ret>0) { printf("buf=%s\n",buf); } else { perror("read fail\n"); return 0; } } } //写一个简单的聊天客户端 可以进行读写操作 }
-----------------------------------------------------------------------------------------------------------
程序运行时必须先运行服务器程序,再运行客户端程序,并且设置端口和服务器ip地址
相关文章推荐
- TCP SOCKET服务器|客户端简单实现
- golang简单实现一个基于TLS/SSL的 TCP服务器和客户端
- python socket实现简单的(TCP/UDP)服务器/客户端
- Golang实现简单tcp服务器03 -- 文本广播式聊天服务器/客户端
- Golang实现简单tcp服务器02 -- 实现echo服务器/客户端
- erlang tcp服务器和客户端的简单实现
- Linux下的C语言编程——简单实现tcp客户端和服务器
- 使用套接字实现简单TCP服务器客户端模型
- 从简单到复杂实现TCP客户端服务器通信
- Java学习笔记(一)------服务器&客户端一对一通信小程序实现(TCP)
- 用Java实现简单的文件上传服务器和客户端
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
- 基于TCP的服务器和客户端的简单收发Demo
- Java 利用套接字Socket实现简单的服务器与客户端通信
- 实现简单UDP服务器客户端模型
- Android与JavaIO实现简单Echo服务器与客户端
- Unity3D笔记——TCP简单服务器和客户端的连接和异步接受
- 简单socket服务(三)实现多客户端向服务器发送数据并保证服务器接收到数据
- 网络编程:使用Socket实现简单的服务器和客户端的通信