网络 套接字编程 TCP、UDP
2016-10-25 14:02
676 查看
网络是大端
发数据从低地址发, 先发的是 高位的数据。
收数据从高位收,先收到的数据存放到低地址。
TCP 是 流式的 所用套接字也是流式的
文件描述符
socket 是 IP 加 端口号
用到的函数:
telnet CTRL+] 就可以进入命令行了
问题描述:服务器与 客户端连接后 马上 kill掉服务器 然后又启动服务器 出现 Address already in use的错误 linux中等上半分钟 就可以启动服务器了
[bozi@localhost tcp]$ ./server_1_simple
bind and listen success, wait accept...
get connect, ip is :13.0.0.0 port is : 1032
^C
[bozi@localhost tcp]$ ./server_1_simple
bind error, error code is : 98, errno string is :#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define LISTEN_QUEUE_NUM 50
void* handler_data(void* arg)
{
int client_socket = (int)arg;
printf("create a new thread...new socket:%d\n", client_socket);
char buf[1024];
while (1)
{
ssize_t _s = read(client_socket, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
printf("client %s\n", buf);
write(client_socket, buf, strlen(buf));
}
else if (_s == 0) // client close
{
printf("client is close\n");
break;
}
else
{
break;
}
}
close(client_socket);
return (void*)0;
}
int main()
{
int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(9999);
local.sin_addr.s_addr = htonl(INADDR_ANY);
// local.sin_addr.s_addr = inet_addr("192.168.1.1");
//
if (bind(listen_sock,(struct sockaddr*)&local, sizeof(local)) < 0)
{
perror("bind");
exit(2);
}
if (listen(listen_sock, LISTEN_QUEUE_NUM) < 0)
{
perror("listen");
exit(3);
}
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
// signal(SIGCHLD, collect_child);
while (1)
{
int new_fd = accept(listen_sock, (struct sockaddr*)&peer, &len);
if (new_fd > 0)
{
pthread_t tid ;
pthread_create(&tid, NULL, handler_data, (void*)new_fd);
pthread_detach(tid);
}
}
close(listen_sock);
return 0;
}练习代码:【客户端代码】#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void usage(const char *proc)
{
printf("%s [ip] [port]\n", proc);
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
usage(argv[0]);
return 3;
}
int conn = socket(AF_INET, SOCK_STREAM, 0);
if (conn < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_port = htons(atoi(argv[2]));
remote.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(conn, (struct sockaddr*)&remote, sizeof(remote)) < 0)
{
perror("connect");
return 2;
}
char buf[1024];
while(1)
{
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
//buf[_s - 1] = '\0';// 去掉\n
buf[_s] = '\0';
write(conn, buf, strlen(buf));
read(conn , buf, sizeof(buf) - 1);
printf("server echo : %s\n", buf);
}
else
{
perror("read ----");
break;
}
}
return 0;
}练习代码:[b]#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void usage(const char *proc)
{
printf("%s [ip] [port]\n", proc);
}
int main(int argc, char* argv[])
{
if (argc != 3)
{
usage(argv[0]);
return 3;
}
int conn = socket(AF_INET, SOCK_STREAM, 0);
if (conn < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(argv[1]);
remote.sin_port = htons(atoi(argv[2]));
if (connect(conn, (struct sockaddr*)&remote, sizeof(remote)) < 0)
{
perror("connect");
return 2;
}
char buf[1024];
while (1)
{
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
write(conn, buf, strlen(buf));
read(conn, buf, sizeof(buf) - 1);
printf("server echo:%s\n", buf);
}
else
{
exit(55);
}
}
close(conn);
return 0;
}运行结果:
[bozi@localhost tcp3]$ netstat -alpt
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
.............................................
tcp 0 0 localhost:distinct localhost:56683 ESTABLISHED 3451/./server
tcp 0 0 localhost:56683 localhost:distinct ESTABLISHED 3450/./client
tcp 1 0 192.168.174.158:60487 ip-42-99-128-139.pacne:http CLOSE_WAIT 2969/clock-applet
tcp 0 0 localhost:56682 localhost:distinct ESTABLISHED 3411/./client
tcp 0 0 localhost:distinct localhost:56682 ESTABLISHED 3412/./server
udp编程
1)创建socket时,数据格式为:SOCK_DGRAM(数据块)
2)数据收发用recvfrom和sendto ssize_t recvfrom(int socket,void *restrict buffer,size_t length,int flags,struct sockaddr * restrict address,socklen_t *restrict address_len); restrict:类型限定符,限定约束指针。表明该指针是访问这个数据队形的唯一的方式 补充一点: void *memcpy( void * restrict dest ,const void * restrict src,sizi_t n) 这是一个很有用的内存复制函数,由于两个参数都加了restrict限定,所以两块区域不能重叠,即 dest指针所指的区域,不能让别的指针来修改,即src的指针不能修改. 相对应的别一个函数 memmove(void *dest,const void * src,size_t)则可以重叠。 socket: 已连接的套接字 buffer:接收数据的缓冲区 length:缓冲区长度
flags :调用操作方式 address:指向装有源地址的缓冲区(传出型参数) address_len:指向源地址缓冲区的实际长度(传入传出型参数) ssize_t sendto(int socket,const void*buffer,size_t length,int flags,struct sockaddr* dest_addr,socklen_t len); socket:已连接套接字 buffer:包含待发送数据的缓冲区 length:buffer缓冲区数据的长度 flags:调用方式标志位 dest_addr:指向目的套接字的地址
len:dest_addr所指地址的长度
练习代码:【服务器 】#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BF_SIZE 1024
int main(const int argc,const char* argv[])
{
if (argc != 3)
{
printf("please enter %s [ip] [port]\n",argv[0]);
exit(1);
}
int fd = socket(AF_INET, SOCK_DGRAM,0 );//SOCK_DGRAM 数据报套接口
if (fd < 0)
{
perror("socket");
exit(2);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr(argv[1]);
local.sin_port = htons(atoi(argv[2]));
if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0)
{
perror("bind");
return 2;
}
struct sockaddr_in remote;
socklen_t len = sizeof(remote);
while (1)
{
char buf[BF_SIZE];
memset(buf, '\0', sizeof(buf));
ssize_t _s = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&remote, &len);// 注意len取地址 sendto 中不用
if (_s > 0)
{
printf("client :[ip:%s][port:%d] %s", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port), buf);
}
else if (_s == 0)
{
printf("read done...\n");
}
else
{
break;
}
}
close(fd);
return 0;
}练习代码:【客户端】#include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
int main(const int argc,const char* argv[] )
{
if (argc != 3)
{
printf("please enter %s [ip] [port]\n", argv[0]);
return 1;
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket");
return 2;
}
int port = atoi(argv[2]);
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(argv[1]);
remote.sin_port = htons(port);
while (1)
{
char buf[1024];
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
}
_s = sendto(fd, buf, strlen(buf),0, (struct sockaddr*)&remote, sizeof(remote));
}
return 0;
}运行:[bozi@localhost ~]$ netstat -atup
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
.......
udp 0 0 localhost:distinct32 *:* 4671/./server
udp 0 0 *:60703 *:* 4673/./client
本文出自 “城市猎人” 博客,请务必保留此出处http://alick.blog.51cto.com/10786574/1836297
发数据从低地址发, 先发的是 高位的数据。
收数据从高位收,先收到的数据存放到低地址。
TCP 是 流式的 所用套接字也是流式的
文件描述符
socket 是 IP 加 端口号
用到的函数:
$ netstat -nltp测试的时候 用 telnet
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 10091/./server_1_si
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN -
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:60790 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp 0 0 :::47946 :::* LISTEN -
tcp 0 0 :::111 :::* LISTEN -
tcp 0 0 :::22 :::* LISTEN -
tcp 0 0 :::23 :::* LISTEN -
tcp 0 0 ::1:631 :::* LISTEN -
tcp 0 0 ::1:25 :::* LISTEN -
telnet CTRL+] 就可以进入命令行了
问题描述:服务器与 客户端连接后 马上 kill掉服务器 然后又启动服务器 出现 Address already in use的错误 linux中等上半分钟 就可以启动服务器了
[bozi@localhost tcp]$ ./server_1_simple
bind and listen success, wait accept...
get connect, ip is :13.0.0.0 port is : 1032
^C
[bozi@localhost tcp]$ ./server_1_simple
bind error, error code is : 98, errno string is :#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define LISTEN_QUEUE_NUM 50
void* handler_data(void* arg)
{
int client_socket = (int)arg;
printf("create a new thread...new socket:%d\n", client_socket);
char buf[1024];
while (1)
{
ssize_t _s = read(client_socket, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
printf("client %s\n", buf);
write(client_socket, buf, strlen(buf));
}
else if (_s == 0) // client close
{
printf("client is close\n");
break;
}
else
{
break;
}
}
close(client_socket);
return (void*)0;
}
int main()
{
int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(9999);
local.sin_addr.s_addr = htonl(INADDR_ANY);
// local.sin_addr.s_addr = inet_addr("192.168.1.1");
//
if (bind(listen_sock,(struct sockaddr*)&local, sizeof(local)) < 0)
{
perror("bind");
exit(2);
}
if (listen(listen_sock, LISTEN_QUEUE_NUM) < 0)
{
perror("listen");
exit(3);
}
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
// signal(SIGCHLD, collect_child);
while (1)
{
int new_fd = accept(listen_sock, (struct sockaddr*)&peer, &len);
if (new_fd > 0)
{
pthread_t tid ;
pthread_create(&tid, NULL, handler_data, (void*)new_fd);
pthread_detach(tid);
}
}
close(listen_sock);
return 0;
}练习代码:【客户端代码】#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void usage(const char *proc)
{
printf("%s [ip] [port]\n", proc);
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
usage(argv[0]);
return 3;
}
int conn = socket(AF_INET, SOCK_STREAM, 0);
if (conn < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_port = htons(atoi(argv[2]));
remote.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(conn, (struct sockaddr*)&remote, sizeof(remote)) < 0)
{
perror("connect");
return 2;
}
char buf[1024];
while(1)
{
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
//buf[_s - 1] = '\0';// 去掉\n
buf[_s] = '\0';
write(conn, buf, strlen(buf));
read(conn , buf, sizeof(buf) - 1);
printf("server echo : %s\n", buf);
}
else
{
perror("read ----");
break;
}
}
return 0;
}练习代码:[b]#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void usage(const char *proc)
{
printf("%s [ip] [port]\n", proc);
}
int main(int argc, char* argv[])
{
if (argc != 3)
{
usage(argv[0]);
return 3;
}
int conn = socket(AF_INET, SOCK_STREAM, 0);
if (conn < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(argv[1]);
remote.sin_port = htons(atoi(argv[2]));
if (connect(conn, (struct sockaddr*)&remote, sizeof(remote)) < 0)
{
perror("connect");
return 2;
}
char buf[1024];
while (1)
{
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
write(conn, buf, strlen(buf));
read(conn, buf, sizeof(buf) - 1);
printf("server echo:%s\n", buf);
}
else
{
exit(55);
}
}
close(conn);
return 0;
}运行结果:
[bozi@localhost tcp3]$ netstat -alpt
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
.............................................
tcp 0 0 localhost:distinct localhost:56683 ESTABLISHED 3451/./server
tcp 0 0 localhost:56683 localhost:distinct ESTABLISHED 3450/./client
tcp 1 0 192.168.174.158:60487 ip-42-99-128-139.pacne:http CLOSE_WAIT 2969/clock-applet
tcp 0 0 localhost:56682 localhost:distinct ESTABLISHED 3411/./client
tcp 0 0 localhost:distinct localhost:56682 ESTABLISHED 3412/./server
udp编程
UDP(User Datagram Protocol,用户数据报协议)是一个简单的、面向数据报的无连接协议,提供了快速但不一定可靠的传输服务。 UDP与TCP相比主要有以下区别。 1.UDP速度比TCP快 由于UDP不需要先与对方建立连接,也不需要传输确认,因此其数据传输速度比TCP快得多。 2.UDP有消息边界 使用UDP不需要考虑消息边界问题,使用上比TCP简单 3.UDP可以一对多传输 利用UDP可以使用广播或组播的方式同时向子网上的所有客户发送信息。这一点也比TCP方便。 4.UDP可靠性不如TCP 与TCP不同,UDP并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP称为不可靠的传输协议。 5.UDP不像TCP那样能保证有序传输 UDP不能确保数据的发送和接收顺序。对于突发性的数据报,有可能会乱序。事实上,UDP的这种乱序性基本上很少出现,通常只会在网络非常拥挤的情况下才有可能发生UDP编程
1)创建socket时,数据格式为:SOCK_DGRAM(数据块)
2)数据收发用recvfrom和sendto ssize_t recvfrom(int socket,void *restrict buffer,size_t length,int flags,struct sockaddr * restrict address,socklen_t *restrict address_len); restrict:类型限定符,限定约束指针。表明该指针是访问这个数据队形的唯一的方式 补充一点: void *memcpy( void * restrict dest ,const void * restrict src,sizi_t n) 这是一个很有用的内存复制函数,由于两个参数都加了restrict限定,所以两块区域不能重叠,即 dest指针所指的区域,不能让别的指针来修改,即src的指针不能修改. 相对应的别一个函数 memmove(void *dest,const void * src,size_t)则可以重叠。 socket: 已连接的套接字 buffer:接收数据的缓冲区 length:缓冲区长度
flags :调用操作方式 address:指向装有源地址的缓冲区(传出型参数) address_len:指向源地址缓冲区的实际长度(传入传出型参数) ssize_t sendto(int socket,const void*buffer,size_t length,int flags,struct sockaddr* dest_addr,socklen_t len); socket:已连接套接字 buffer:包含待发送数据的缓冲区 length:buffer缓冲区数据的长度 flags:调用方式标志位 dest_addr:指向目的套接字的地址
len:dest_addr所指地址的长度
练习代码:【服务器 】#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BF_SIZE 1024
int main(const int argc,const char* argv[])
{
if (argc != 3)
{
printf("please enter %s [ip] [port]\n",argv[0]);
exit(1);
}
int fd = socket(AF_INET, SOCK_DGRAM,0 );//SOCK_DGRAM 数据报套接口
if (fd < 0)
{
perror("socket");
exit(2);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr(argv[1]);
local.sin_port = htons(atoi(argv[2]));
if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0)
{
perror("bind");
return 2;
}
struct sockaddr_in remote;
socklen_t len = sizeof(remote);
while (1)
{
char buf[BF_SIZE];
memset(buf, '\0', sizeof(buf));
ssize_t _s = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&remote, &len);// 注意len取地址 sendto 中不用
if (_s > 0)
{
printf("client :[ip:%s][port:%d] %s", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port), buf);
}
else if (_s == 0)
{
printf("read done...\n");
}
else
{
break;
}
}
close(fd);
return 0;
}练习代码:【客户端】#include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
int main(const int argc,const char* argv[] )
{
if (argc != 3)
{
printf("please enter %s [ip] [port]\n", argv[0]);
return 1;
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket");
return 2;
}
int port = atoi(argv[2]);
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = inet_addr(argv[1]);
remote.sin_port = htons(port);
while (1)
{
char buf[1024];
ssize_t _s = read(0, buf, sizeof(buf) - 1);
if (_s > 0)
{
buf[_s] = '\0';
}
_s = sendto(fd, buf, strlen(buf),0, (struct sockaddr*)&remote, sizeof(remote));
}
return 0;
}运行:[bozi@localhost ~]$ netstat -atup
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
.......
udp 0 0 localhost:distinct32 *:* 4671/./server
udp 0 0 *:60703 *:* 4673/./client
本文出自 “城市猎人” 博客,请务必保留此出处http://alick.blog.51cto.com/10786574/1836297
相关文章推荐
- java socket, java套接字, java网络编程, java tcp, java udp
- 网络 套接字编程 TCP、UDP
- 网络编程与并发-TCP/UDP套接字、粘包问题、Socket编程、并发编程、FTP作业
- 网络编程一:概述、网络模型、TCP\UDP、Socket套接字、UDP发送和接收、UDP聊、阻塞式方法
- 【Python网络编程】利用Python进行TCP、UDP套接字编程
- 网络编程与并发-TCP/UDP套接字、粘包问题、Socket编程、并发编程、FTP作业
- TCP/UDP的套接字网络编程模型
- java 网络编程 [网络传输] [协议] [UDP与TCP] [套接字] [URL与URI]
- [python] 专题七.网络编程之套接字Socket、TCP和UDP通信实例
- Python网络编程之TCP与UDP协议套接字用法示例
- 【转载】 基于UDP、TCP协议的C#网络编程
- 网络编程 --IP、TCP、UDP校验和算法
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 简单TCP Socket 通信
- JAVA网络编程入门的两个demo(TCP+UDP)
- [Linux网络编程笔记]传输协议TCP和UDP简介
- JAVA网络编程入门的两个demo(TCP+UDP)
- [转贴]基于UDP、TCP协议的C#网络编程之一
- 基于UDP、TCP协议的C#网络编程之一
- 剖析网络编程-TCP&UDP
- 网络编程的基础知识 TCP、UDP 学习日记