From:
TCP
server
socket流程:socket()创建套接字,bind()绑定,listen()监听,accept()接收然后才是send(),recv()什么
的,最后关闭。
client
socket流程: socket(),connect(),recv(),send()最后close()。注意一:Linux服务器 1024 以下的端口号必须以超级管理员身份使用,或者授权。这个和Windows就不一样。
也就是说,楼主如果使用默认的端口号7,则运行你的这个程序应先切换到root身份,然后再这个权限下运行你写的那个程序。
以普通用户身份,系统不会把1024下的端口号给你用的。
//-------
建议在做Linux下网络编程的的时候,实验端口最好在10000以上,因为如果你的Linux装的服务软件多的话,可能会遇到端口号冲突的问题。别让这小问题绊住你。
端口号取值范围 0 - 65535(即2的16次方)编译 gcc -o TCPEchoClient TCPEchoClient.c DieWithError.c
对于编译好的 程序 ./TCPEchoClient 127.0.0.1 "echo this"
如果程序运行结果正常 :Recived :echo this
但是显示 connect refuse
TCPEchoClient.c
C/C++ code
- #include <stdio.h> /* for printf() and fprintf() */
-
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
-
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
-
#include <stdlib.h> /* for atoi() and exit() */
-
#include <string.h> /* for memset() */
-
#include <unistd.h> /* for close() */
-
-
#define RCVBUFSIZE 32 /* Size of receive buffer */
-
-
void DieWithError(char *errorMessage); /* Error handling function */
-
-
int main(int argc, char *argv[])
-
{
-
int sock; /* Socket descriptor */
-
struct sockaddr_in echoServAddr; /* Echo server address */
-
unsigned short echoServPort; /* Echo server port */
-
char *servIP; /* Server IP address (dotted quad) */
-
char *echoString; /* String to send to echo server */
-
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
-
unsigned int echoStringLen; /* Length of string to echo */
-
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv()
-
and total bytes read */
-
-
if ((argc < 3) || (argc > 4)) /* Test for correct number of arguments */
-
{
-
fprintf(stderr, "Usage: %s []\n",
-
argv[0]);
-
exit(1);
-
}
-
-
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
-
echoString = argv[2]; /* Second arg: string to echo */
-
-
if (argc == 4)
-
echoServPort = atoi(argv[3]); /* Use given port, if any */
-
else
-
echoServPort = 7; /* 7 is the well-known port for the echo service */
-
-
/* Create a reliable, stream socket using TCP */
-
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-
DieWithError("socket() failed");
-
-
/* Construct the server address structure */
-
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
-
echoServAddr.sin_family = AF_INET; /* Internet address family */
-
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
-
echoServAddr.sin_port = htons(echoServPort); /* Server port */
-
-
/* Establish the connection to the echo server */
-
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
-
DieWithError("connect() failed");
-
-
echoStringLen = strlen(echoString); /* Determine input length */
-
-
/* Send the string to the server */
-
if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
-
DieWithError("send() sent a different number of bytes than expected");
-
-
/* Receive the same string back from the server */
-
totalBytesRcvd = 0;
-
printf("Received: "); /* Setup to print the echoed string */
-
while (totalBytesRcvd < echoStringLen)
-
{
-
/* Receive up to the buffer size (minus 1 to leave space for
-
a null terminator) bytes from the sender */
-
if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
-
DieWithError("recv() failed or connection closed prematurely");
-
totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */
-
echoBuffer[bytesRcvd] = '\0'; /* Terminate the */
-
printf("%s", echoBuffer); /* Print the echo buffer */
-
}
-
-
printf("\n"); /* Print a final linefeed */
-
-
close(sock);
-
exit(0);
-
}
DieWithError.c
C/C++ code
- #include <stdio.h> /* for perror() */
-
#include <stdlib.h> /* for exit() */
-
-
void DieWithUserMessage(const char *msg,const char *detail)
-
{
-
fputs(msg,stderr);
-
fputs(":",stderr);
-
fputs("detail",stderr);
-
fputs("\n",stderr);
-
exit(1);
-
}
-
void DieWithError(char *errorMessage)
-
{
-
perror(errorMessage);
-
exit(1);
-
}
非阻塞的socket
O_NONBLOCK 和O_NDELAY 差不多,但第一个更好,因为返回的是-1,第二个是0,内容的结尾就是0
UNP的16.3和16.4节 介绍了 非阻塞的connect,
利用好error code, errno是一个全局变量,每个线程一个errno,而不是程序(或者准确的说,进程)。C标准中说明了它的规范,由编译器实现。可能由宏定义来实现。
The
integer errno is set by system calls (and some
library functions) to indicate what went wrong.
只需要包含 error.h就可以使用,没有显式的定义。
RAW socket:Raw sockets allow new IPv4 protocols to be implemented in user space. A
raw socket receives or
sends the
raw datagram not including link level headers.
The IPv4 layer generates an IP header when sending a packet unless the IP_HDRINCL socket option is enabled on the socket. When it is enabled, the
packet must contain an IP header. For receiving the IP header is always included in the packet.
Linux协议栈:sys_socketcall
Linux 中的 socket 结构是 struct sock,这个结构是在 linux/include/net/sock.h 中定义的。
阅读(2405) | 评论(0) | 转发(0) |