socket编程(tcp)
来源:互联网 发布:软件著作权 版权 编辑:程序博客网 时间:2024/05/22 17:06
使用TCP协议的流程图
TCP 通信的基本步骤如下:
服务端:socket---bind---listen---while(1){---accept---recv---send---close---}---close
客户端:socket----------------------------------connect---send---recv-----------------close
服务器端:
1.头文件包含:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
2.socket函数:生成一个套接口描述符。
原型:intsocket(intdomain,inttype,intprotocol);
参数:domain{AF_INET:Ipv4网络协议AF_INET6:IPv6网络协议}
type{tcp:SOCK_STREAMudp:SOCK_DGRAM}
protocol指定socket所使用的传输协议编号。通常为0.
返回值:成功则返回套接口描述符,失败返回-1。
常用实例:
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
{
perror("socket");
exit(-1);
}
3.bind函数:用来绑定一个端口号和IP地址,使套接口与指定的端口号和IP地址相关联。
原型:intbind(intsockfd,structsockaddr*my_addr,intaddrlen);
参数:sockfd为前面socket的返回值。
my_addr为结构体指针变量
对于不同的socketdomain定义了一个通用的数据结构
struct sockaddr //此结构体不常用
{
unsigned short int sa_family; //调用 socket()时的 domain 参数,即 AF_INET 值。
char sa_data[14]; //最多使用 14 个字符长度
};
此sockaddr结构会因使用不同的socketdomain而有不同结构定义,
例如使用AF_INETdomain,其socketaddr结构定义便为
struct sockaddr_in //常用的结构体
{
unsigned short int sin_family; //即为 sa_family AF_INET
uint16_t sin_port; //为使用的 port 编号
struct in_addr sin_addr; //为 IP 地址
unsigned char sin_zero[8]; //未使用
};
struct in_addr
{
uint32_t s_addr;
};
addrlensockaddr的结构体长度。
通常是计算sizeof(structsockaddr);
返回值:成功则返回0,失败返回-1
常用实例:
struct sockaddr_in my_addr; //定义结构体变量
memset(&my_addr, 0, sizeof(struct sockaddr)); //将结构体清空
//或 bzero(&my_addr, sizeof(struct sockaddr));
my_addr.sin_family = AF_INET; //表示采用 Ipv4 网络协议
my_addr.sin_port = htons(8888); //表示端口号为 8888,通常是大于 1024 的一个值。
//htons()用来将参数指定的 16 位 hostshort 转换成网络字符顺序
my_addr.sin_addr.s_addr = inet_addr("192.168.0.101"); //inet_addr()用来将 IP 地址字符串转
换成网络所使用的二进制数字,如果为 INADDR_ANY,这表示服务器自动填充本机 IP 地址。
if(bind(sfd, (struct sockaddr*)&my_str, sizeof(struct socketaddr)) == -1)
{
perror("bind");
close(sfd);
exit(-1);
}
(注:通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址。)
原型:int listen(int sockfd,int backlog);
参数:sockfd为前面 socket 的返回值.即 sfd
backlog指定同时能处理的最大连接要求,通常为 10 或者 5。最大值可设至 128
返回值:成功则返回 0,失败返回-1
常用实例:
if(listen(sfd, 10) == -1)
{
perror("listen");
close(sfd);
exit(-1);
}
5. accept 函数:接受远程计算机的连接请求,建立起与客户机之间的通信连接。服务器处于监听状态时, 如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。当 accept 函数接受一个连接时,会返回一个新的 socket 标识符, 以后的数据传输和读取就要通过这个新的 socket 编号来处理,原来参数中的 socket 也可以继续使用,继 续监听其它客户机的连接请求。(也就是说,类似于移动营业厅,如果有客户打电话给 10086,此时服 务器就会请求连接,处理一些事务之后,就通知一个话务员接听客户的电话,也就是说,后面的所有操 作,此时已经于服务器没有关系,而是话务员跟客户的交流。对应过来,客户请求连接我们的服务器, 我们服务器先做了一些绑定和监听等等操作之后,如果允许连接,则调用 accept 函数产生一个新的套接 字,然后用这个新的套接字跟我们的客户进行收发数据。也就是说,服务器跟一个客户端连接成功,会 有两个套接字。)
原型:
int accept(int s,struct sockaddr * addr,int * addrlen);
参数:s为前面 socket 的返回值.即 sfdaddr为结构体指针变量,和 bind 的结构体是同种类型的,系统会把远程主机的信息(远程 主机的地址和端口号信息)保存到这个指针所指的结构体中。
addrlen表示结构体的长度,为整型指针
返回值:成功则返回新的 socket 处理代码 new_fd,失败返回-1
常用实例:
struct sockaddr_in clientaddr;
memset(&clientaddr, 0, sizeof(struct sockaddr));int addrlen = sizeof(struct sockaddr);
int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);
if(new_fd == -1)
{
perror("accept");
close(sfd);
exit(-1);
}
printf("%s %d success connect\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));6. recv 函数:用新的套接字来接收远端主机传来的数据,并把数据存到由参数 buf 指向的内存空间
原型:int recv(int sockfd,void *buf,int len,unsigned int flags);
参数:sockfd为前面 accept 的返回值.即 new_fd,也就是新的套接字。 buf表示缓冲区len表示缓冲区的长度
flags通常为 0
返回值:成功则返回实际接收到的字符数,可能会少于你所指定的接收长度。失败返回-1
常用实例:
char buf[512] = {0};
if(recv(new_fd, buf, sizeof(buf), 0) == -1){
perror("recv");
close(new_fd);
close(sfd);
exit(-1);
}
7.send函数:用新的套接字发送数据给指定的远端主机
原型:intsend(ints,constvoid*msg,intlen,unsignedintflags);
参数:s为前面accept的返回值.即new_fd
msg一般为常量字符串
len表示长度
flags通常为0
返回值:成功则返回实际传送出去的字符数,可能会少于你所指定的发送长度。失败返回-1
常用实例:
if(send(new_fd,"hello",6,0)==-1)
{
perror("send");
close(new_fd);
close(sfd);
exit(-1);
}
8.close函数:当使用完文件后若已不再需要则可使用close()关闭该文件,并且close()会让数据写回磁盘,并释放该文件所占用的资源
原型:intclose(intfd);
参数:fd为前面的sfd,new_fd
返回值:若文件顺利关闭则返回0,发生错误时返回-1常用实例:
close(new_fd);
close(sfd);
客户端:
1.connect函数:用来请求连接远程服务器,将参数sockfd的socket连至参数serv_addr指定的服务器IP和端口号上去。
原型:intconnect(intsockfd,structsockaddr*serv_addr,intaddrlen);
参数:sockfd为前面socket的返回值,即sfd (与服务器端一样)
serv_addr为结构体指针变量,存储着远程服务器的IP与端口号信息。addrlen表示结构体变量的长度
返回值:成功则返回0,失败返回-1
常用实例:
structsockaddr_inseraddr;//请求连接服务器
memset(&seraddr,0,sizeof(structsockaddr));
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(8888);//服务器的端口号
seraddr.sin_addr.s_addr=inet_addr("192.168.0.101");//服务器的ip
if(connect(sfd,(structsockaddr*)&seraddr,sizeof(structsockaddr))==-1)
{
perror("connect");
close(sfd);
exit(-1);
}
其他的都一样
- Socket编程练习(TCP)
- SOCKET TCP 编程
- Socket-TCP编程
- TCP socket编程模型
- TCP Socket服务器编程
- 网路编程-TCP-Socket
- socket编程之tcp
- 基本TCP socket编程
- Socket TCP 编程
- Socket 编程(TCP)
- TCP Socket服务器编程
- TCP Socket服务器编程
- socket的tcp编程
- TCP Socket服务器编程
- TCP/IP socket编程
- socket编程基于tcp
- TCP Socket服务器编程
- Tcp SOCKET 编程
- 设计模式-原型模式
- Android Inflater addview导致加载子布局match_parent无效
- java回调机制
- Linux C/C++ 开发遇到 undefined reference to xxx
- 斐波那契数列
- socket编程(tcp)
- Android RecyclerView控件的使用(一)
- MySQL-创建用户、授权用户、撤销用户权限、更改用户密码、删除用户
- ExpressBox 2200
- C语言的发展与特点
- 28.字符串的排列
- Windows在线图片验证Redis+接口+token+Sign+时间戳 Demo
- java基础学习网络编程之UDP和TCP协议 十四 -3
- C#之装箱与拆箱