udp:
1、建立socket套接字2、servaddr初始化(比如端口号)
3、bind 绑定servaddr
4、recvform或者sendto函数调用(也可以用tcp的收发函数,send,read,write)
下面的例子是简单的回射功能,只作用一次。
代码:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#define PORT 8080
int main(void)
{
int fd;
int flag;
fd = socket(AF_INET,SOCK_DGRAM,0);
if(fd<0){
printf("error in open socket\n");
exit(1);
}
struct sockaddr_in servaddr,cliaddr;
bzero(&servaddr,0);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);//端口号
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//udp的话这个可以any
flag = bind(fd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr));//绑定
if(flag<0){
printf("error in bind\n");
exit(1);
}
char buf[128];
memset(buf,0,sizeof(buf));
int len = sizeof(cliaddr);
int n;
n = recvfrom(fd,buf,128,0,(struct sockaddr *)&cliaddr,&len);//接收
printf("receive buf:%s\n",buf);
sendto(fd,buf,n,0,(struct sockaddr *)&cliaddr,len);//回射回去
return 0;
}
TCP服务器:
1、建立socket套接字(SOCK_STREAM:tcp)
2、初始化服务器sockaddr_in参数(主要是端口号,以及类型)
3、应考虑下tcp的重置向—— rc = setsockoptsockfd,SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); int on=1;
4、bind地址
5、监听(listen),把进程转化为一个服务器。
int listen(int sockfd, int backlog); backlog为连接请求队列的最大长度(一般由2到6,一般取5)
6、accept。将从连接请求队列中获得连接信息,创建新的套接字(新的fd),提取最前的一个客户请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
这的addr为客户端的sockaddr_in
7、fork出子进程,用于发送给客户端信息。
代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 5000
int main(void)
{
int fd;
struct sockaddr_in servaddr,cliaddr;
int flag;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
printf("error in socket\n");
return 0;
}
/* init servaddr */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT); //端口
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器的话,这个是any
int on=1;
flag = setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on)); //重置向
if(flag<0){
printf("error in reuseaddr\n");
exit(1);
}
flag = bind(fd,(struct sockaddr *)&servaddr,sizeof(servaddr)); //绑定
if(flag<0){
printf("error in bind\n");
exit(1);
}
flag = listen(fd,5); //开启监听
if(flag<0){
printf("error in listen\n");
exit(1);
}
int len = sizeof(servaddr);
int cfd;
while(1){
if((cfd=accept(fd,(struct sockaddr *)&cliaddr,&len))>=0); //等待客户端连接,创建新套接字
if(fork() == 0){
close(fd); //这个已经没必要存在了
while(1){
char buf[128];
memset(buf,0,sizeof(buf));
int n = 0;
//n = read(cfd,buf,128); //这个也是可以用的
n = recv(cfd,buf,128,0); //用这个,很多书上都用这个
if(n<0){
exit(1);
}
write(cfd,buf,n);
}
}
}
}
TCP客户端
1、建立socket套接字(SOCK_STREAM:tcp)2、初始化服务器的sockaddr_in,特别是端口号以及服务器ip地址
3、connect。尝试建立与服务器的连接。
int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
sockaddr为服务器地址信息
4、send or recv 操作。
代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 5000
int main(void)
{
int fd;
struct sockaddr_in servaddr;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
printf("error in socket\n");
return 0;
}
/* init servaddr */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
if(inet_pton(AF_INET, "172.31.18.207", &servaddr.sin_addr) <= 0){ //服务器的ip要初始化
printf("is not a valid IPaddress/n");
return 0;
}
/* connect to server */
int i;
for(i=0;i<5;i++){
if(connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){ //去链接服务器
perror("connect error");
continue;
}
break;
}
char buf[128];
memset(buf,0,sizeof(buf));
int n = 0;
// n = read(fd,buf,128);
n = recv(fd,buf,128,0);
printf("receive:buf:%s\n",buf);
write(fd,buf,n);
}