日期:2014-05-16  浏览次数:20598 次

socket在Linux下小Demo

Ubuntu的终端用来搞c和c++真是太方便了,哪像windows下的turboC那么麻烦啊!

?

直接vi编辑一个.c 或 .cpp 文件,然后g++ 或 gcc 一编译,直接? ./a.out运行,真是太方便了。

?

不熟悉的函数直接man一下就ok了。好东西啊!

?

?

现在就用这东西学习一下socket吧:

?

1.首先搞一个服务端:

?

vi a.c

?

内容如下:

?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 引入的三个头文件,是必需的:
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
// 两个结构体,下面要用的,实例化了?NO,没有实例化
// 只是重命名了,为什么要这样呢?
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR ;

// 入口main,注意参数,这个是要输入的启动参数,
// 例如:./service 9999,其中9999就是输入的参数
// 是个char数组,可以传入多个参数,按顺序
int main(int argc,char **argv)
{

        // 1.创建套接字
        // 参数:SOCK_DGRAM是基于UDP的socket通信模式,
        // 如果是TCP的话是SOCK_STREAM.
	int fd = socket(AF_INET, SOCK_DGRAM, 0);
	
	// 声明一个服务端和一个客户端的结构体对象:
	SOCKADDR_IN addrSrv ;
	SOCKADDR_IN addrClient;

	// 定义接收和发送的字符串
	char  recvBuf[100] = {0};
	char  sendBuf[100] = {0};

        // 服务端的长度,下面要用到
	int len = sizeof(addrSrv);

	// 服务端的地址,
 	// INADDR_ANY 可接受的客户端是任意地址
	addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(atoi(argv[1]));// 服务端的端口号

	// 绑定套接字和端口
	bind(fd,(struct sockaddr *)&addrSrv,sizeof(addrSrv));


	while(1){
		// 接收客户端信息
		recvfrom(fd, recvBuf, 16, 0, (SOCKADDR*)&addrClient, &len);
		printf("recvBuf :%s\n",recvBuf);

		printf("please input data:\n");
		fgets(sendBuf,100,stdin);
		// 发送给客户端信息
		sendto(fd,sendBuf,20,0,(SOCKADDR*)&addrClient, len);

	}

	// 关闭套接字
	close(fd);
	// 可以有或没有return 1;

}
?

?

2.构建一个客户端:

?

vi b.c

?

代码如下:

?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 引入的三个头文件,是必需的:
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>

typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR ;
int main(int argc,char **argv)
{
	int fd = socket(AF_INET, SOCK_DGRAM, 0);
	SOCKADDR_IN addrSrv ;
	SOCKADDR_IN addrClient;
	char  recvBuf[100] = {0};
	char  sendBuf[100] = {0};
	int len = sizeof(addrClient);

	// 此处的输入的第二个参数是指定服务端的ip地址
	addrSrv.sin_addr.s_addr = inet_addr(argv[2]);
	addrSrv.sin_family = AF_INET;
        // 输入的第一个参数,服务端的端口号
	addrSrv.sin_port = htons(atoi(argv[1]));

// 跟服务端的不同之处,不用绑定套接字和端口
//	bind(fd,(struct sockaddr *)&addrSrv,sizeof(addrSrv));

	while(1)
	{
		printf("please inpur data\n");
		fgets(sendBuf,100,stdin);
		sendto(fd,sendBuf,20,0,(SOCKADDR*)&addrSrv, len);
		recvfrom(fd, recvBuf, 16, 0, (SOCKADDR*)&addrClient, &len);
		printf("recvBuf %s\n",recvBuf);
	}

	close(fd);
	return 0;
}
?

两者差别不多,只两点:1.客户端需要指定服务端的ip和端口,所以执行的时候需要输入端口和ip。

?

??????????????????????????????????????????? 2.客户端不需要绑定端口。

?

?

3.编译:

?

gcc a.c -o server

?

?

gcc b.c -o client

?

?

4.运行:

?

./server 9999

?

从另一个终端运行:

?

./client? 9999 192.168.*.*

?

?

5.结果,不同的终端代表不同的进程,通过输入和打印出的信息就能证明两者开始交互了。

?

?

?

?