spacer.gif实验5 基本套接字实验

要掌握的函数:

2.1 函数

int socket(int  domain,int type,int protocol)

一般情况下使用:

socket(AF_INET,SOCK_STREAM,0);

返回的是socket 套接字的编号

2.2 数据类型:

struct sockaddr_in(表示IP  地址和端口号)

有三个重要的域:

sin_family

sin_port

sin_addr

每次必须设置

例如程序

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

server_addr.sin_port=htons(81);

将地址设为0.0.0.0 将端口设置为81,采用协议是互联网协议

2.3 函数bind

通常使用

bind(sockfd,(struct  sockaddr*)(&server_addr),sizeof(server_addr));

第一个参数是绑定的套接字编号,第二个是要绑定的地址的指针,第三个地址结

构体大小,这样把一个套接字和一个IP 地址+端口绑定了

2.4 函数listen

通常情况listen(sockfd,128);监听某个套接字(绑定的),阻塞,如果有客户端对

我进行连接,则阻塞停止进入下一步程序运行。

2.5 函数accept

通常使用:

newfd=accept(sockfd,(struct  sockaddr*)(&client_addr),&size);

第一个参数为刚刚从监听中的那个套接字编号,第二个参数为客户的地址结构体

的地址(这个实际是一个输出参数),第三个参数是地址结构体的大小(也是输出

参数),这是系统根据受到的TCP 包的头字节进行填充的。

返回值很重要,是一个新的套接字编号。事实上以后通过这个套接字进行通信了。

2.6 客户端函数:

connect(sockfd,(struct  sockaddr*)(&addr), sizeof (addr));

注意addr 其实是一个服务器的sockaddr_in 类型

2.7 读函数

read(new_fd,buf,BUFSIZE);

第一个参数是新的套接字编号


spacer.gif第二个参数是缓冲区起始地址

第三个是缓冲区大小

把套接字受到的内容写道缓冲区中

2.8 写函数

write(new_fd,buf,BUFSIZE);

第一个参数是新的套接字编号

第二个参数是缓冲区起始地址

第三个是缓冲区大小

把缓冲区的内容送到套接字中(逻辑上就是送到网络中)

××××××××××××××××××××××××

服务器的过程

1 socket 函数产生监听套接字

2 设置地址结构体(sockaddr_int)的监听地址(0.0.0.0)和端口(例如82) 和协议

族(AF_INET

3 将地址结构体和监听套接字绑定

4 调用listen,等待客户端的连接

5 当客户端有连接时(listen

6 调用accept() 返回出新的套接字,作为读写套接字,并且填充了客户地址结

构体

accept(sockfd,(struct sockaddr*)(&client_addr),&size);

7 读客户端发来的信息read(newfd,buf,BUFSIZE) 客户端过程的第3

8 分析读的信息,写信息到套接字中

××××××××××××××××××××××××

客户端过程:

1 socket 函数产生连接套接字

2 设置地址结构体(sockaddr_int)的连接的地址(127.0.0.1)和端口(例如82)

协议族(AF_INET

3 连接服务器connct()

例如connect(sockfd,(struct  sockaddr*)(&server_addr),sizeof server_addr);

4 写套接字write(sockfd,buf,strlen(buf))

5 读套接字read(sockfd,buf,BUFSIZE)

××××××××××××××××××××××××

简单服务器:

#include  <stdio.h>

#include  <stdlib.h>

#include  <errno.h>

#include  <string.h>

#include  <sys/socket.h>

#include  <sys/types.h>

#include  <arpa/inet.h>


spacer.gif#define BUFSIZE 128

#define PORT  82

char buf[BUFSIZE+1];

int main()

{

int sockfd;

int new_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

socklen_t size;

//创建服务器监听套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1){fprintf(stderr,"socket  error:%s",strerror(errno)); exit(-1);}

//为监听套接字准备IP  地址和端口号

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

server_addr.sin_port=htons(PORT);

//将监听套接字绑定到地址和端口上

int bret=bind(sockfd,(struct  sockaddr*)(&server_addr),sizeof(server_addr));

if(bret==-1)

{fprintf(stderr,"bind  error %s\r\n",strerror(errno));exit(-1);};

//监听

int lret=listen(sockfd,128);

if(lret==-1)

{fprintf(stderr,"listen  error %s\r\n",strerror(errno));exit(-1);};

while(1)

{

size=sizeof(struct sockaddr_in);

//接收客户端连接并且创建服务器连接套接字

new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size);

if(new_fd==-1)

{fprintf(stderr,"accept  error %s\r\n",strerror(errno));exit(-1);};

printf("\r\nServergotanconnection

%s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

from


spacer.gif//循环读入客户端发来的消息

for(;;)

{

int z=read(new_fd,buf,BUFSIZE);

if(z<0)

{fprintf(stderr,"listen  error %s\r\n",strerror(errno));exit(-1);};

if(z==0) {printf("client quit! \r\n");;break;}

buf[z]=0;

//打印buf  中的内容,注意一定要打印\r\n 否则放在缓冲区出不来

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

}

}

}

简单服务器的客户端程序:

#include  <stdio.h>

#include  <stdlib.h>

#include  <errno.h>

#include  <string.h>

#include  <sys/socket.h>

#include  <sys/types.h>

#include  <arpa/inet.h>

#include  <unistd.h>

#include  <netdb.h>

#define PORT  82

#define BUFSIZE  128

char buf[BUFSIZE+1];

int main()

{

int sockfd;

int new_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

//创建客户端套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno));  exit(-1);}

//创建服务器地址和端口号结构体

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

inet_aton("127.0.0.1",&server_addr.sin_addr);


spacer.gifserver_addr.sin_port=htons(PORT);

printf("\r\nip地址:%s

%d\r\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));

//连接服务器

int cret=connect(sockfd,(struct  sockaddr*)(&server_addr),sizeof server_addr);

if(cret==-1)

{fprintf(stderr,"connect  error:%s",strerror(errno)); exit(-1);}

printf("\r\n  conncet to Server

for(;;)

{

%s\r\n",inet_ntoa(server_addr.sin_addr));

scanf("%s",buf);//键盘输入

if(!strcasecmp(buf,"QUIT"))

{printf("end client");break;};

int z=write(sockfd,buf,strlen(buf));

if(z<0){fprintf(stderr,"write  error:%s",strerror(errno)); exit(-1);}

printf("client has sent %s  to the server \r\n",buf);

}// end of  for

}

回文的服务器

当客户端输入1,则服务器将当前时间发送给客户端

当客户端输入2,则服务器将hello  发送给客户端

当客户端输入其他,则服务器将其回文发送给客户端

#include  <stdio.h>

#include  <stdlib.h>

#include  <errno.h>

#include  <string.h>

#include  <sys/socket.h>

#include  <sys/types.h>

#include  <arpa/inet.h>

#include  <time.h>

#define BUFSIZE  128

#define PORT  82

char buf[BUFSIZE+1];

void back(char  *s)

{

int i=0;

int len=strlen(s);


spacer.giffor(;i<len/2;i++)

{

char temp=s[i];

s[i]=s[len-1-i];

s[len-1-i]=temp;

}

}

int main()

{

int sockfd;

int new_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

socklen_t size;

//创建服务器监听套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1){fprintf(stderr,"socket  error:%s",strerror(errno)); exit(-1);}

//为监听套接字准备IP  地址和端口号

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

server_addr.sin_port=htons(PORT);

//将监听套接字绑定到地址和端口上

int bret=bind(sockfd,(struct  sockaddr*)(&server_addr),sizeof(server_addr));

if(bret==-1)

{fprintf(stderr,"bind  error %s\r\n",strerror(errno));exit(-1);};

//监听

int lret=listen(sockfd,128);

if(lret==-1)

{fprintf(stderr,"listen  error %s\r\n",strerror(errno));exit(-1);};

while(1)

{

size=sizeof(struct sockaddr_in);

//接收客户端连接并且创建服务器连接套接字

new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size);

if(new_fd==-1)


spacer.gif{fprintf(stderr,"accept error %s\r\n",strerror(errno));exit(-1);};

printf("\r\nServergotanconnection

%s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

//循环读入客户端发来的消息

for(;;)

{

int z=read(new_fd,buf,BUFSIZE);

if(z<0)

{fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);};

if(z==0) {printf("client quit! \r\n");;break;}

buf[z]=0;

//打印buf  中的内容,注意一定要打印\r\n 否则放在缓冲区出不来

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

//回应文

time_t now=time(NULL);

//printf("debug1: %d %s %d",new_fd,buf,strlen(buf));

if(strcasecmp(buf,"1")==0)

sprintf(buf,"%s",ctime(&now));

else if(strcasecmp(buf,"2")==0)

{

sprintf(buf,"%s","hello  world!");

}

else back(buf);

z= write(new_fd,buf,strlen(buf));

if(z<0){fprintf(stderr,"listen error  %s\r\n",strerror(errno));exit(-1);};

}

}

}

回文的客户端程序:

#include  <stdio.h>

#include  <stdlib.h>

#include  <errno.h>

#include  <string.h>

#include  <sys/socket.h>

#include  <sys/types.h>

#include  <arpa/inet.h>

#include  <unistd.h>

#include  <netdb.h>

#define PORT  82

from


spacer.gif#define BUFSIZE 128

char buf[BUFSIZE+1];

int main()

{

int sockfd;

int new_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

struct hostent *host;//需要netdb.h,报错特别奇怪不会怀疑到没有include

netdb.h

//建立host

//创建客户端套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno));  exit(-1);}

//创建服务器地址和端口号结构体

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

inet_ntoa("127.0.0.1",  &server_addr.sin_addr);

server_addr.sin_port=htons(PORT);

printf("\r\n  ip %s %d\r\n",  inet_ntoa(server_addr.sin_addr),

ntohs(server_addr.sin_port));

//连接服务器

int cret=connect(sockfd,(struct  sockaddr*)(&server_addr),sizeof server_addr);

if(cret==-1)

{fprintf(stderr,"connect  error:%s",strerror(errno)); exit(-1);}

printf("\r\n  conncet to Server %s\r\n",inet_ntoa(server_addr.sin_addr));

for(;;)

{

scanf("%s",buf);//键盘输入

if(!strcasecmp(buf,"QUIT"))

{printf("end client");break;}

int z=write(sockfd,buf,strlen(buf));

if(z<0){fprintf(stderr,"write  error:%s",strerror(errno)); exit(-1);}

printf("client has sent %s  to the server \r\n",buf);

}// end of  for

}

并发服务器(多进程)

#include  <stdio.h>


spacer.gif#include <stdlib.h>

#include  <errno.h>

#include  <string.h>

#include  <sys/socket.h>

#include  <sys/types.h>

#include  <arpa/inet.h>

#include  <time.h>

#define BUFSIZE  128

#define PORT  82

char buf[BUFSIZE+1];

void back(char  *s)

{

int i=0;

int len=strlen(s);

for(;i<len/2;i++)

{

char temp=s[i];

s[i]=s[len-1-i];

s[len-1-i]=temp;

}

}

int main()

{

int sockfd;

int new_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

socklen_t size;

//创建服务器监听套接字

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1){fprintf(stderr,"socket  error:%s",strerror(errno)); exit(-1);}

//为监听套接字准备IP  地址和端口号

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

server_addr.sin_port=htons(PORT);

//将监听套接字绑定到地址和端口上


spacer.gifint bret=bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(server_addr));

if(bret==-1)

{fprintf(stderr,"bind  error %s\r\n",strerror(errno));exit(-1);};

//监听

int lret=listen(sockfd,128);

if(lret==-1)

{fprintf(stderr,"listen  error %s\r\n",strerror(errno));exit(-1);};

while(1)

{

size=sizeof(struct sockaddr_in);

//接收客户端连接并且创建服务器连接套接字

new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size);

if(new_fd==-1)

{fprintf(stderr,"accept  error %s\r\n",strerror(errno));exit(-1);};

printf("\r\nServergotanconnection

%s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

int ret=fork();

if(ret==0)

{

//循环读入客户端发来的消息

for(;;)

{

int z=read(new_fd,buf,BUFSIZE);

if(z<0)

{fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);};

if(z==0){printf("client%s:%dquit!process

%d\r\n",inet_ntoa(client_addr.sin_addr),htons(client_addr.sin_port),getpid());;exit(0);

}

buf[z]=0;

//打印buf  中的内容,注意一定要打印\r\n 否则放在缓冲区出不来

printf("process%ugetmessagefromclient%s%d

%s\r\n",getpid(),inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),buf);

//回应文

time_t now=time(NULL);

if(strcasecmp(buf,"1")==0)

sprintf(buf,"%s",ctime(&now));

else if(strcasecmp(buf,"2")==0)

{

from


spacer.gifsprintf(buf,"%s","hello  world!");

}

else back(buf);

z= write(new_fd,buf,strlen(buf));

if(z<0){fprintf(stderr,"listen error  %s\r\n",strerror(errno));exit(-1);};

}

}

}

}