您的位置:首页 > 理论基础 > 计算机网络

Linux下TCP客户端和服务器代码编写

2015-10-16 08:39 603 查看
一、各部分功能:
服务器:主动建立服务程序,等待客户端连接,相应客户端的请求
客户端:当有需求时,主动连接服务器,发出服务请求

二、书写顺序:
1、先写服务器程序,然后用telnet 模拟客户端远程登录
2、再写客户端程序,登录写好的服务器
3、最后写客户端和服务器通信的语句。

三、先写服务器程序,然后用telnet 模拟客户端远程登录
1、socket
int socket (int domain, int type, int protocol);
功能:建立socket文件
输入参数:
domain 是地址族网络通信 填写PF_INET (AF_INET)
本地通信 填写PF_UNIX (AF_UNIX)
type  // 套接字类型
SOCK_STREAM   // 流式套接字 ---TCP协议
SOCK_DGRAM    // 数据报套接字--UDP协议
protocol 参数通常置为0

返回值:成功返回:socket文件描述符
失败返回:-1 并置错误码

socket例子:
int listenfd = 0;
if((listenfd = socket(PF_INET,SOCK_STREAM,0)) == -1)

perror("socket");
return -1;
}

2、建立网络地址
网络地址原型:
struct sockaddr_in    struct sockaddr_un
{           
u_short sin_family;       // 地址族, AF_INET,2 bytes
u_short sin_port;         // 端口,2 bytes
struct in_addr sin_addr;  // IPV4地址,4 bytes
char sin_zero[8];         // 8 bytes unused,作为填充
}; 
IPv4地址结构
// internet address  
struct in_addr
{
in_addr_t  s_addr;            // u32 network address 
};
定义一个struct sockaddr_in类型的变量并清空
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
填充地址信息
serveraddr.sin_family = PF_INET;
serveraddr.sin_port = htons(8888); 
serveraddr.sin_addr.s_addr = inet_addr(“172.16.7.111”);

3、bind
int bind(int listenfd,struct sockaddr *serveraddr, int addrlen) ; 

功能:将创建好的socket文件和一个网络地址进行绑定
输入参数:
listenfd: 调用返回的文件描述符   
serveraddr:填充后的地址              
addrlen: serveraddr地址结构的长度    
 
返回值:成功:0或 失败返回-1,并错误码
 
bind例子
if(bind(listenfd, (struct sockaddr*)(&serveraddr), sizeof(serveraddr)) == -1)
{
perror("bind");
return -1;
}
4、listen函数

int listen (int listenfd, int backlog);
功能:将一个普通套接字变为监听套接字,同时设置等待队列最大长度。
输入参数:
listenfd:监听连接的套接字
backlog
指定了正在等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求。
DoS(拒绝服务)攻击即利用了这个原理,非法的连接占用了全部的连接数,造成正常的连接请求被拒绝。
返回值:成功 0 或 失败-1

listen例子:

listen(listenfd, 5);

5、accept函数
int accept(int listenfd, struct sockadd *addr, socklen_t *addrlen) ;
功能:当有客户端连接请求时,建立连接,返回连接套接字
输入参数:
sockfd : 监听套接字  socket_fd
addr : 对方地址   
 struct sockaddr_in clinet_addr;            NULL
 bzero(client_addr,sizeof(client_addr));
 传参数:(struct sockaddr *)(&client_addr)
addrlen:地址长度  
 socklen_t len =sizeof(client_addr)        NULL
 传参数:&len
返回值:已建立好连接的套接字或-1

accept例子:
定义存放客户端地址的变量:
struct sockaddr_in clinet_addr;                  
bzero(client_addr,sizeof(client_addr)); 
定义存放客户端地址长度的变量:  
socklen_t len =sizeof(client_addr)
定义接受连接套接字的文件描述符变量:
int connect_fd = 0;                           
if((connect_fd = accept(socket_fd,(struct sockaddr *)(&client_addr),&len) )== -1)
{
perror("accept");
return -1;
}

6、打印客户端地址:
printf("clientaddr-->IP:%s\n",inet_ntoa(clientaddr.sin_addr));
printf("clientaddr-->PORT: %d \n",ntohs(clientaddr.sin_port));

7、close函数
close(socket_fd);
close(connect_fd);

四、再写客户端程序,登录写好的服务器
1、创建socket

2、填充服务器的网络地址

3、connect函数
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
功能:连接服务器
输入参数:
sockfd : socket返回的文件描述符
serv_addr : 服务器端的地址信息? 
addrlen : serv_addr的长度 
返回值:成功 0 或 失败-1

if(connect(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1)
{
perror("connect");
return -1;
}

五、最后写客户端和服务器通信的语句。
1、在客户端添加发送函数
ssize_t  send(int  socket,  const  void  *buffer,  size_t  length, int flags);
功能:发送信息
输入参数:
socket :文件描述符
buffer : 发送缓冲区首地址
length : 发送的字节数
flags : 发送方式(通常为0)
返回值:
成功:实际发送的字节数
失败:-1, 并设置errno

2、在服务器端添加接收函数
ssize_t  recv(int  socket,  const  void  *buffer,  size_t  length, int flags);
功能:接收信息
输入参数:
socket:文件描述符
buffer : 发送缓冲区首地址
length : 发送的字节数
flags : 接收方式(通常为0)
返回值:
成功:实际接收的字节数
失败:-1, 并设置errno

注意: socket 是连接套接字
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: