概述
一.实验目的
理解tcp传输客户端服务器端通信流程
二.实验平台
MAC OS
三.实验内容
编写TCP服务器套接字程序,程序运行时服务器等待客户的连接,一旦连接成功,则显示客户的IP地址、端口号,并向客户端发送字符串。
四.实验原理
使用TCP套接字编程可以实现基于TCP/IP协议的面向连接的通信,它分为服务器端和客户端两部分,其主要实现过程如下
四.实验流程
服务器端流程
1.创建socket
socket是一个结构体,被创建在内核中
sockfd=socket(AF_INET,SOCK_STREAM,0); //AF_INT:ipv4, SOCK_STREAM:tcp协议
2.调用bind函数
将socket和地址(包括ip、port)绑定。
需要定义一个结构体地址,以便于将port的主机字节序转化成网络字节序
struct sockaddr_in serveraddr; //地址结构体
bind函数
bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))
3.listen监听,将接收到的客户端连接放入队列
listen(sockfd,10) //第二个参数是队列长度
4.调用accept函数,从队列获取请求,返回socket描述符
如果无请求,将会阻塞,直到获得链接
int fd=accept(sockfd, (struct sockaddr*)&clientaddr, &clientaddr_len);
5.调用IO函数和客户端双向通信
6.关闭accept返回的socket
close(fd);
服务器端代码:
#include "iostream"
#include "netdb.h"
#include "stdio.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "unistd.h"
#include "arpa/inet.h"
#include "string.h"
#include "memory.h"
#include "signal.h"
#include "time.h"
int sockfd;
void sig_handler(int signo)
{
if(signo==SIGINT)
{
printf("Server close n");
close(sockfd);
exit(1);
}
}
//输出连接上来的客户端相关信息
void out_addr(struct sockaddr_in *clientaddr)
{
//将端口从网络字节序转成主机字节序
int port =ntohs(clientaddr->sin_port);
char ip[16];
memset (ip,0,sizeof(ip));
inet_ntop(AF_INET,
&clientaddr->sin_addr.s_addr,ip,sizeof(ip));
printf("client:%s(%d)connectedn",ip,port);
}
void do_service(int fd)
{
//获取系统时间
long t=time(0);
char *s=ctime(&t);
size_t size=strlen(s)*sizeof(char);
//将服务器端的系统时间写到客户端
if(write(fd,s,size)!=size)
{
perror("write error");
}
}
int main(int argc,char *argv[])
{
if(argc<2)
{
printf("usage:%s #portn",argv[0]);
exit(1);
}
if(signal(SIGINT,sig_handler)==SIG_ERR)
{
perror("signal sigint error");
exit(1);
}
/*1. 创建socket
AF_INT:ipv4
SOCK_STREAM:tcp协议
*/
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
perror("socket error");
exit(1);
}
/*2:调用bind函数绑定socket和地址*/
struct sockaddr_in serveraddr;
memset(&serveraddr,0,sizeof(serveraddr));
//往地址中填入ip,port,internet类型
serveraddr.sin_family=AF_INET; //ipv4
serveraddr.sin_port=htons(atoi(argv[1])); //htons主机字节序转成网络字节序
serveraddr.sin_addr.s_addr=INADDR_ANY;
if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0)
{
perror("bind error");
exit(1);
}
/*3:调用listen函数监听(指定port监听)
通知操作系统区接受来自客户顿的连接请求
第二个参数:指定队列长度
*/
if(listen(sockfd,10)<0)
{
perror("listen error");
}
/*4:调用accept函数从队列中获得一个客户端的请求连接
*/
struct sockaddr_in clientaddr;
socklen_t clientaddr_len=sizeof(clientaddr);
while(1){
int fd=accept(sockfd,
(struct sockaddr*)&clientaddr,
&clientaddr_len);
if(fd<0){
perror("accept error");
continue;
}
/*5:调用IO函数(read/write)和
连接的客户端进行双向通信
*/
out_addr(&clientaddr);
do_service(fd);
/*6.关闭socket*/
close(fd);
}
return 0;
}
客户端代码:
#include "netdb.h"
#include "sys/socket.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "memory.h"
#include "unistd.h"
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc<3)
{
printf("usage:%s ip port n",argv[0]);
exit(1);
}
/*步骤1:创建socket*/
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("socket error");
exit(1);
}
struct sockaddr_in serveraddr;
memset(&serveraddr,0,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(atoi(argv[2]));
//主机字节序转换成网络字节序
inet_pton(AF_INET,argv[1],
&serveraddr.sin_addr.s_addr);
/*步骤2:客户端调用connect函数连接到服务器
*/
if(connect(sockfd,(struct sockaddr*)&serveraddr,
sizeof(serveraddr))<0)
{
perror("connect error");
exit(1);
}
/*步骤3:调用IO函数(read/write)和服务器端双向通信*/
char buffer[1024];
memset(buffer,0,sizeof(buffer));
size_t size;
if((size=read(sockfd,
buffer,sizeof(buffer)))<0)
{
perror("read error");
}
if(write(STDOUT_FILENO,buffer,size)!=size)
{
perror("write error");
}
}
最后
以上就是英俊小海豚为你收集整理的基于TCP的客户端、服务器端socket编程的全部内容,希望文章能够帮你解决基于TCP的客户端、服务器端socket编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复