Linux下(c++)实现socket(一)
Linux下实现socket(c++)
近期学习了linux下的简单socket编程,在这里与大家分享一下,有疑问或者错误欢迎大家讨论和指出.
socket是什么?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。即Socket提供了操作上述特殊文件的接口.使用这些接口可以实现网络编程。
TCP和UDP![]()
流程图
TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,在正式通信之前必须建立起连接。UDP(User Data Protocol,用户数据报协议)是一个非连接的协议。因此TCP的服务器模式比UDP的服务器模式多了listen,accept函数。TCP客户端比UDP客户端多了connect函数。这里着重介绍TCP下socket简单编程.
TCP使用socket创建服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、绑定IP地址、端口等信息到socket上,用函数bind();
3、开启监听,用函数listen();
4、接收客户端上来的连接,用函数accept();
5、收发数据,用函数send()和recv(),或者read()和write();
6、关闭网络连接;
7、关闭监听;
TCP使用socket创建
Client端一般步骤是:
TCP使用socket创建客户端一般步骤是:
1、创建一个socket,用函数socket();
2、连接服务器,用函数connect();
3、收发数据,用函数send()和recv(),或者read()和write();
4、关闭网络连接;
client端程序的具体实现:
需要完成的任务
- 创建嵌套字( socket() )
- 向服务器发送连接请求( connect() )
- 和服务器进行通信( send()/recv() )
- 关闭嵌套字( close() )
函数使用说明
1.socket()
需要的头文件
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
声明
int socket(int domain, int type, int protocol);
参数说明:
(1) domain:
Name Purpose Man page
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK AppleTalk ddp(7)
AF_PACKET Low level packet interface packet(7)
AF_ALG Interface to kernel crypto API
(2)type
The socket has the indicated type, which specifies the communication semantics. Currently defined types are:
SOCK_STREAM
Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported.//提供顺序、可靠、双向、基于连接的字节流。可支持带外数据传输机制.tcp是需要连接的,udp不需要连接.
SOCK_DGRAM
Supports datagrams (connectionless, unreliable messages of a fixed maximum length).
SOCK_SEQPACKET
Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each input system call.
SOCK_RAW
Provides raw network protocol access.
SOCK_RDM
Provides a reliable datagram layer that does not guarantee ordering.
SOCK_PACKET
Obsolete and should not be used in new programs; see packet(7).
(3)protocol(协议)
protocol:指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
(4)RETURN VALUE
On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set appropriately.//如果创建错误,将返回-1
2.connec( sockfd, addr, addrlen):返回值为-1时连接失败
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
addr:连接目标服务器的协议族。
addr_len:对应的地址的长度。
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。
该函数的第一个参数指定接收端套接字描述符;
第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明buf的长度;
第四个参数一般置0。
4.send
int send( SOCKET s, const char FAR *buf, int len, int flags );
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。
客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。
该函数的第一个参数指定发送端套接字描述符;
第二个参数指明一个存放应用程序要发送数据的缓冲区;
第三个参数指明实际要发送的数据的字节数;
第四个参数一般置0。
client端程序代码:此处服务器ip用的是我阿里云的,端口80,读者可以在terminal运行时输入你要访问的ip和端口.
#include <iostream> #include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
using namespace std;
int main(int argc,char **argv)
{
int client, server;
// int portNum ; // note the server and clients Ip are the same
bool isExit = false;
int bufsize = 1024;
char buffer[bufsize];
// char *ip = "182.254.18.159";
struct sockaddr_in server_addr;
if(argc != 3)
{
cout<<"usesge:socket_client ipaddress poet. client 182.154.18.159 80 "<<endl;
}
int portNum = atoi(argv[2]);//端口号
//init socket
client = socket(AF_INET,SOCK_STREAM,0);
if(client < 0)
{
cout<<"Error creating socket"<<endl;
exit(1);
}
cout<<"socket client have been created test"<<endl;
server_addr.sin_port = htons(portNum);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);//inet_addr () 函数将 Internet 主机地址 cp 从 IPv4 数字和点符号转换为网络字节顺序中的二进制数据。
// connecting socket server
if (connect(client,(struct sockaddr*)&server_addr,sizeof(server_addr)) == 0)
cout<<"connecting to server"<<endl;
recv(client,buffer,bufsize,0);
cout<<"connection confirmed"<<endl;
cout<< "enter # to end the connect"<<endl;
do{
cout<<"client:";
do{
cin>> buffer;
send(client,buffer,bufsize,0);
if(*buffer == '#')
{
send(client,buffer,bufsize,0);
*buffer = '*';
isExit = true;
}
*
}while(*buffer != 42);
cout<<"server: ";
do{
recv(client,buffer,bufsize,0);
cout<<buffer<<"";
if(*buffer == '#')
{
*buffer = '*';
isExit = true;
}
}while(*buffer !=42);
cout<<endl;
}while(!isExit);
cout<<"connection terminated ..."<<endl;
cout<<"goodbye"<<endl;
close(client);
return 0;
}