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

Linux TCP客户端、服务器编程模型及实例

2016-12-05 20:17 495 查看

Linux TCP客户端、服务器编程模型及实例

服务器模型:

1、绑定IPv4的地址(INADDR_ANY)和端口号(8888)

int listenfd, sockfd, opt = 1;

struct sockaddr_in server, client;

新建socket

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if(listenfd < 0){
perror("Create socket fail.");
return -1;

}

设置地址可重用功能,防止异常退出无法短时间打开server

if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)

{

    perror("Error, set socket reuse addr failed");

  return -1;

}

bzero(&server, sizeof(server));

server.sin_family = AF_INET;

server.sin_port   = htons(8888);

server.sin_addr.s_addr  = htonl(INADDR_ANY);

2、将套接字转换成监听套接字

len = sizeof(struct sockaddr);

if(bind(listenfd, (struct sockaddr *)&server, len)<0){
perror("bind error.");

    return -1;

}

listen(listenfd, MAX_LISTEN_QUE);

3、等待客户端连接

sockfd = accept(listenfd, (struct sockaddr *)&client, &len);

if(sockfd < 0)

{
perror("accept error.");
return -1;

}

4、读取客户端数据

read(sockfd,buf,100);

printf("%s\n",buf);

5、写据给客户端

time_now = time(NULL);

bzero(&buf,100);

strcpy(buf,(char *)ctime(&time_now));

printf("time:%s\n",buf);

write(sockfd,buf,strlen(buf));

6、关闭套接字

close(sockfd);

close(listenfd);

实例代码:

头文件apue.h

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<strings.h>
#include<time.h>

#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h> //inet


源文件3.c

/*************************************************************************
> File Name: 3.c
> Created Time: 2016年12月01日 星期四 10时53分36秒
************************************************************************/
/*
*this is time server
* */

#include"apue.h"
#define MAX_LISTEN 10
int main(int argc,char *argv[])
{
int listenfd,sockfd,opt = 1;
struct sockaddr_in server,client;
int len;
time_t time_now;
char buf[100];

listenfd = socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
perror("create socket failed\n");
return -1;
}

if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))<0)
{
perror("set socket reuse addr failed\n");
return -1;
}

bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(8888);
server.sin_addr.s_addr = htonl(INADDR_ANY);//代表该主机上的所有IP地址,如果机器上有多个网卡或者虚拟机的话,若不使用此方法容易出错

len = sizeof(struct sockaddr);
if(bind(listenfd,(struct sockaddr *)&server,len)<0)
{
perror("bind error\n");
return -1;
}

listen(listenfd,MAX_LISTEN);//可以连接的最大数据

while(1) //迭代服务器,同时不能连接多个客户端,当一个客户端关闭后就可以重新连接第二个客户端
{
sockfd = accept(listenfd,(struct sockaddr *)&client,&len);//sockaddr 和sockaddr_in可以相互转化的
if(sockfd<0)
{
perror("accept error\n");
return -1;
}

read(sockfd,buf,100);
printf("%s\n",buf);

time_now = time(NULL);
bzero(&buf,100);
strcpy(buf,(char *)ctime(&time_now));
printf("time:%s\n",buf);
write(sockfd,buf,strlen(buf));
printf("sockfd:%d\n",sockfd);
close(sockfd);
}

close(listenfd);
return 0;
}


客户端模型:

1、创建一个IPv4(AF_INET)的字节流(SOCK_STREAM)套接字

int sockfd;

struct sockaddr_in server_ip;

if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

{

    perror("socket error\n");

    return -1;

}

2、连接到IP地址为(192.168.1.108、127.0.0.1),端口号为8888的服务器

 bzero(&server_ip,sizeof(server_ip));

//equal to memset()

server_ip.sin_family  =AF_INET;

server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");

server_ip.sin_port = htons(5678);

if(connect(sockfd,(struct sockaddr*)&server_ip,sizeof(server_ip))<0)

{

    perror("connect error\n");

    return 0;

}

3、写一个数据到服务器

strcpy(buf,(char *)"I am client");

if(write(sockfd,buf,strlen(buf))<0)

{

    printf("error,write error\n");

    return -1;

}

4、接收服务器传回来的数据并显示到标准输出

bytes = read(sockfd,buf,100);

if(bytes<0)

{

    printf("error,read failed\n");

    return -1;

}

5、关闭套接字

close(sockfd);

实例代码:

头文件同上;

源文件2.c

/*************************************************************************
> File Name: 2.c
> Created Time: 2016年12月01日 星期四 09时52分46秒
************************************************************************/
/*
*this is client to get server time
* */
#include"apue.h"

int main(int agtc,char *argv[])
{
int sockfd;
struct sockaddr_in server_ip;
char buf[100];
int bytes;
if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)
{
perror("socket error\n");
return -1;
}

bzero(&server_ip,sizeof(server_ip));
//equal to memser()
server_ip.sin_family  =AF_INET;
server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");
server_ip.sin_port = htons(8888);

if(connect(sockfd,(struct sockaddr*)&server_ip,sizeof(server_ip))<0)
{
perror("connect error\n");
return 0;
}

bzero(&buf,100);
strcpy(buf,(char *)"I am client");
if(write(sockfd,buf,strlen(buf))<0)
{
printf("error,write error\n");
return -1;
}

bzero(&buf,100);
bytes = read(sockfd,buf,100);
if(bytes<0)
{
printf("error,read failed\n");
return -1;
}

if(bytes ==0)
{
printf("Server close connection\n");
return -1;
}

if(bytes >0)
{
printf("read bytes %d\n",bytes);
printf("time is %s\n",buf);
}

close(sockfd);
return 0;
}


注意:server中添加了setsockopt函数

#include <sys/types.h>

#include <sys/socket.h>

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

如果运行server的时候,若未正常退出内核有时候会提示地址已经在使用,此时可用此函数来重用地址,否则在几分钟内无法重启server的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐