基于C/S的简单TCP网络编程

来源:互联网 发布:ps4装linux 编辑:程序博客网 时间:2024/05/22 13:32

基本常用函数介绍

1.int socket(int domain, int type, int protocol);

创建一个socket套接字,并返回一个套接字描述符第一个参数用以选择套字的协议族常用参数极其目的如下:第二个参数用以选择套接字的传输方式,在TCP协议中我们选择**SOCK_STREAM**使我们的创建的套接字成为 一个有序的,可靠的,双向数据流。第三个参数为0。返回值>0为socket描述符,等于0说明创建socket错误。
  1. void bzero(void *s, size_t n);

     bzero()函数可以将前N个字节的信息设置为'\0'。 无返回值 参数: *s ——想要的更改的数据  n ——想要更改数据的长度
    1. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      功能:连接服务器
      参数
      sockfd——我们之前创建的套接字描述符
      sockaddr的结构体,其内部定义如下:
      struct sockaddr_in {
      short sin_family /AF_INET/
      u_short sin_port; /端口号,网络字节顺序/
      struct in_addr sin_addr; /IP地址,网络字节顺序/
      char sin_zero[8]; /填充字节,必须为全零/
      };
      我们可以在sockaddr中定义端口号,套接字类型,ip地址如下:

      addrlen——地址结构长度

      设置代码:

    ClientSock1.sin_family = AF_INET;    ClientSock1.sin_port = htons(PORT1);    ClientSock1.sin_addr.s_addr = inet_addr("127.0.0.1");
连接代码
if(connect(sockfd1,(struct sockaddr*)&ClientSock1,ClientLen1)==-1){        printf("connect error");        exit(1);    }

返回值:
0 -成功 ,-1 - 失败,errno 为错误代码

4.int bind(int sockfd,struct sockaddr *myaddr,int addrlen);
功能:绑定本地地址和端口
参数:
sockfd-socket描述符
myaddr-自己的地址
addrlen-地址结构长度
返回值:
0-成功,-1-失败,errno为错误代码
注意:
服务器和客户端均可以绑定socket地址,但客户端通常不绑定自己的socket地址,而是系统随机分配一个端口,由该端口和本机ip地址填充套接字地址。

if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){        printf("bind error");        exit(1);    }

5.int listen(int sockfd,int qlen)
功能:监听本地地址和端口
参数:
sockfd-已绑定的socket描述符
qlen - socket能处理的最大并发连接数
返回值
0-成功,-1-失败,errno为错误代码

listen(sockfd,BACKLOG);

6.int accept(int sockfd,struct sockaddr *clientaddr,int addrlen);
功能:接受连接
参数:
sockfd-socket描述符
clientaddr-客户端地址
addrlen-地址结构长度
返回值

0-成功,返回新的socket描述符标识已接受的连接 ,-1-失败,errno为错误代码

new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);    if(new_fd == -1){        printf("accept error");        exit(1);    }

7.int read(int fd,char *buf,int len);
功能:从socket读取数据
参数:
fd-socket描述符
buf-接收数据缓冲区
len-要读取数据大小
返回值
≥0-成功,-1-失败,errno为错误代码

说明:

1.系统接收缓冲区中的数据大于参数len时返回len
2.缓冲区中的数据小于参数len时返回实际长度
3.接收缓冲区中没有数据时read函数阻塞,出现下列情况时返回收到数据:

     连接被关闭,返回0       连接被复位,返回错误      阻塞过程中收到中断信号,errno=EINTR      读取完整数据的read_all函数

8.int write(int fd,char *buf,int len);

参数:
同上

9.int close(int sockfd)
功能:关闭socket
参数:
sockfd-socket描述符
返回值
0-成功,-1-失败,errno为错误代码
说明
调用close只是将对sockfd的引用减1,直到对sockfd的引用为0时才清除sockfd ,TCP协议将继续使用 sockfd,直到所有数据发送完成

实际案例说明

现在我们用上述函数实现一个简单的CS模型:包含一个客户端,两个服务器
客户端同时连接服务器1,服务器2。
客户端生成两个随机数,将其发给服务器1,服务器2
服务器1接受数据,并返回两个数的和
服务器2接受数据,并返回两个数的差

代码如下:

client.c

#include <stdio.h>#include <stdlib.h>#include <time.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#define PORT1 3002#define PORT2 4001#define MAXDATASIZE 128int main(){    int sockfd1,ClientLen1,sockfd2,ClientLen2,a,b;    struct sockaddr_in ClientSock1,ClientSock2;    char buf[MAXDATASIZE];    srand(time(NULL));    a = random()%100;    b = random()%100;    sockfd1 = socket(AF_INET,SOCK_STREAM,0);//创建套接字    if(sockfd1==-1){        printf("create sockfd1 error");        exit(1);    }    //填充套接字地址    bzero(&ClientSock1,sizeof(ClientSock1));    ClientSock1.sin_family = AF_INET;    ClientSock1.sin_port = htons(PORT1);    ClientSock1.sin_addr.s_addr = inet_addr("127.0.0.1");    ClientLen1 = sizeof(ClientSock1);    //连接服务器    if(connect(sockfd1,(struct sockaddr*)&ClientSock1,ClientLen1)==-1){        printf("connect error");        exit(1);    }    bzero(buf,sizeof(buf));    sprintf(buf,"%d",a);    write(sockfd1,buf,MAXDATASIZE);    bzero(buf,sizeof(buf));    sprintf(buf,"%d",b);    write(sockfd1,buf,MAXDATASIZE);    bzero(buf,sizeof(buf));    read(sockfd1,buf,sizeof(buf));    printf("server1's reply:%s\n",buf);    sleep(1);    sockfd2 = socket(AF_INET,SOCK_STREAM,0);    if(sockfd2 == -1){        printf("create sockfd2 error");        exit(1);    }    bzero(&ClientSock2,sizeof(ClientSock2));    ClientSock2.sin_family = AF_INET;    ClientSock2.sin_port = htons(PORT2);    ClientSock2.sin_addr.s_addr = inet_addr("127.0.0.1");    ClientLen2 = sizeof(ClientSock2);    if(connect(sockfd2,(struct sockaddr*)&ClientSock2,ClientLen2)==-1){        printf("connect2 error");        exit(1);    }    bzero(buf,sizeof(buf));    sprintf(buf,"%d",a);    write(sockfd2,buf,MAXDATASIZE);    bzero(buf,sizeof(buf));    sprintf(buf,"%d",b);    write(sockfd2,buf,MAXDATASIZE);    bzero(buf,sizeof(buf));    read(sockfd2,buf,MAXDATASIZE);    printf("server2's reply:%s\n",buf);    close(sockfd1);    close(sockfd2);}

server1.c //接收并返回和

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 3002#define MAXDATASIZE 128#define BACKLOG 5int main(){    int sockfd,new_fd,a,b,result;    struct sockaddr_in serverAddr,clientAddr;    char buf[MAXDATASIZE];    socklen_t serverLen,clientLen;    sockfd = socket(AF_INET,SOCK_STREAM,0);    bzero(&serverAddr,sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(PORT);    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);    serverLen = sizeof(serverAddr);    if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){        printf("bind error");        exit(1);    }    listen(sockfd,BACKLOG);    for(;;){    clientLen = sizeof(clientAddr);    new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);    if(new_fd == -1){        printf("accept error");        continue;    }    bzero(buf,sizeof(buf));    read(new_fd,buf,MAXDATASIZE);    a = atoi(buf);    sleep(1);    bzero(buf,sizeof(buf));    read(new_fd,buf,MAXDATASIZE);    b = atoi(buf);    result = a + b;    bzero(buf,sizeof(buf));    sprintf(buf,"%d",result);    write(new_fd,buf,MAXDATASIZE);    close(new_fd);}    close(sockfd);}

server2.c //返回差

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 4001#define MAXDATASIZE 128#define BACKLOG 5int main(){    int sockfd,new_fd,a,b,result;    struct sockaddr_in serverAddr,clientAddr;    char buf[MAXDATASIZE];    socklen_t serverLen,clientLen;    sockfd = socket(AF_INET,SOCK_STREAM,0);    bzero(&serverAddr,sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(PORT);    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);    serverLen = sizeof(serverAddr);    if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){        printf("bind error");        exit(1);    }    listen(sockfd,BACKLOG);    clientLen = sizeof(clientAddr);    new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);    if(new_fd == -1){        printf("accept error");        exit(1);    }    bzero(buf,sizeof(buf));    read(new_fd,buf,MAXDATASIZE);    a = atoi(buf);    sleep(1);    bzero(buf,sizeof(buf));    read(new_fd,buf,MAXDATASIZE);    b = atoi(buf);    result = a - b;    bzero(buf,sizeof(buf));    sprintf(buf,"%d",result);    write(new_fd,buf,MAXDATASIZE);    close(new_fd);    close(sockfd);}

注意:

    客户端多次发给服务器信息,如果想要分离出这些信息,可以使用sleep()函数使服务器休眠一秒钟。    不然服务器会全部接受客户端发来的信息,并将其储存在buf中。
0 0
原创粉丝点击