面向连接的套接字编程实例

 一、客户机程序代码

1、程序:client.c

2、目的:创建一个套接字,通过网络连接一个服务器,并打印来自服务器的信息

#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5188

extern int errno;
char localhost[] = "localhost";
main(int argc, char *argv[]){
	struct hostent *ptrh;
	struct sockaddr_in servaddr;
	int sockfd;
	int port;
	char* host;
	int n;
	char buf[1000];
	memset((char*)& servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	if(argc > 2){
		port = atoi(argv[2]);
	}else{
		port = PROTOPORT;
	}
	if(port > 0){
		servaddr.sin_port = htons((u_short)port);
	}else{
		fprintf(stderr,"bad port number %s\n",argv[2]);
	}
	if(argc > 1){
		host = argv[1];
	}else{
		host = localhost;
	}
	ptrh = gethostbyname(host);
	if((char*)ptrh == NULL){
		fprintf(stderr,"invalid host:%s\n",host);
	exit(1);
	}
	memcpy(&servaddr.sin_addr,ptrh->h_addr,ptrh->h_length);
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd < 0){
		fprintf(stderr,"socket creation failed\n");
		exit(1);
	}
	if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0){
		fprintf(stderr,"connect failed\n");
		exit(1);
	}
	n = recv(sockfd, buf, sizeof(buf), 0);
	while(n > 0){
		write(1,buf,n);
		n = recv(sockfd, buf, sizeof(buf), 0);
	}
	close(sockfd);
	exit(0);
}

 二、服务器实例代码

1、程序:server.c

2、目的:分配一个套接字,然后反复执行如下几步:

1)等待客户的下一个连接

2)发送一个短消息给客户

3)关闭与客户的连接

4)转向第1步

#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5188
#define QLEN 6
int visits = 0;
main(int argc, char* argv[])
{
	struct hostent* ptrh;
	struct sockaddr_in servaddr;
	struct sockaddr_in clientaddr;
	int listenfd;
	int clientfd;
	int port;
	int alen;
	char buf[1000];
	memset( (char*)& servaddr, 0, sizeof(servaddr) );
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = INADDR_ANY;
	if(argc > 1){
		port = atoi(argv[1]);
	}else{
		port = PROTOPORT;
	}
        if(port > 0){
		servaddr.sin_port = htons( (u_short)port );
	}else{
		fprintf( stderr, "bad port number %s\n", argv[1] );
		exit(1);
	}
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if(listenfd < 0){
		fprintf( stderr, "socket creation failed\n");
			exit(1);
	}
	if( bind( listenfd, (struct sockaddr *)& servaddr, sizeof(servaddr)) < 0){
		fprintf(stderr,"bind failed\n");
		exit(1);
	}
	if(listen(listenfd, QLEN)<0){
		fprintf(stderr,"listen filed\n");
		exit(1);
	}
	while(1){
	alen = sizeof(clientaddr);
	if((clientfd = accept(listenfd, (struct sockaddr *)& clientaddr, &alen)) < 0){
		fprintf(stderr, "accept failed\n");
		exit(1);
	}
	visits++;
	sprintf(buf,"this server has been contacted %d time \n", visits);
	send(clientfd, buf, strlen(buf), 0);
	close(clientfd);
	}
}

三、实操

1、创建一个文件夹和两个文件(如何创建见Linux基本命令的那篇文章),接着输入上文的代码。

2、在文件夹里打开终端,先输入gcc -v看看虚拟机是否安装gcc,然后输入gcc -o server.out server.c ,最后再输入./server.out 看是否出现闪动的小光标。

 3、缩小页面,打开另一个终端,分别输入gcc -o client.out client.c./client.out,即可实现连接。

四、补充

1、#define是宏定义,PROTOPORT是端口号,5188是自己设定的,后面出现PROTOPORT都用5188来替换。

2、argc表示参数个数,argv表示字符串内容,arg[0]是程序的名称,后面的参数从arg[1]开始都按顺序放入字符串数组中,arg数至少是1个。

3、char buf[1000]表示把想发出去的东西先存下来。

4、memset是清空的意思,malloc后的内存块里面的内容不确定,可能是任意值。

5、servaddr.sin_family = AF_INET表示IPV4,即请IPV4进行网间通信。

6、INADDR_ANY是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,你可以收到发送到所有有效地址上数据包。

7、SOCK-STREAM连接表示流式套接字,使用TCP协议;SOCK-DGRAM无连接表示数据报套接字,使用UDP协议。

8、accept接受请求,while循环里转一圈,之后继续监听。

9、stderr接收成功后返回新的套接字描述符,和之前那个区分开来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值